生产环境之前可以正常使用imap协议收取邮件,突然有一天报错Failed to load IMAP envelope,可以确定邮件服务器、账号密码、配置都是正确的,使用foxmail可以正常连接并成功收取邮件,因此可以推测java代码可能有兼容性问题,连接服务器的代码如下,开启mail.debug后,打印日志可以看到已经成功使用imap连接到服务器
public void connect() throws Exception{
Properties props = new Properties();
props.put("mail.host", config.getServer());
props.put("mail." + config.getProtocol() + ".timeout", 60000);
props.put("mail." + config.getProtocol() + ".connectiontimeout", 6000);
props.setProperty("mail.store.protocol", config.getProtocol());
props.setProperty("mail." + config.getProtocol() + ".host", config.getServer());
props.setProperty("mail." + config.getProtocol() + ".port", String.valueOf(config.getPort()));
if(config.isDebug()){
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");
}
if(config.isSsl()){
props.put("mail." + config.getProtocol() + ".socketFactory.port", String.valueOf(config.getPort()));
props.put("mail." + config.getProtocol() + ".starttls.enable", config.isTtlEnable());
props.put("mail." + config.getProtocol() + ".ssl.protocols", "TLSv1.2");
//启用明文验证
//props .setProperty("mail." + config.getProtocol() + ".auth.plain.disable", "false");
props.setProperty("mail." + config.getProtocol() + ".socketFactory.fallback","false");
// 设置授权码验证
//props.put("mail." + config.getProtocol() + ".auth", "true");
props.put("mail." + config.getProtocol() + ".ssl.enable", "true");
props.put("mail." + config.getProtocol() + ".ssl.trust", "*");
props.put("mail." + config.getProtocol() + ".socketFactory.class", "javax.net.ssl.SSLSocketFactory");
}
// 创建Session实例对象
Session session = Session.getInstance(props);
// 创建IMAP协议的Store对象
store = session.getStore(config.getProtocol());
// 连接邮件服务器
store.connect(config.getUsername(),config.getPassword());
// 获得收件箱
folder = store.getFolder("INBOX");
// 以只读模式打开收件箱
folder.open(Folder.READ_ONLY);
}
mail使用的是1.4.7版本,从服务器读取邮件的代码如下:
/**
* 读取cnt封邮件
*/
public void receiveByCount(int cnt) throws Exception {
log.info("开始收取邮件");
long t0 = System.currentTimeMillis();
cnt--;
int n = folder.getMessageCount();
if(n > 0){
int from = Math.max(1,n - cnt);
Message[] messages = folder.getMessages(from,n);
log.info("共收取到{}封邮件",messages.length);
for (int i = messages.length - 1; i >= 0; i--) {
log.info("开始读取第{}封邮件",i+1);
long t = System.currentTimeMillis();
String uid ;
if(folder instanceof IMAPFolder){
uid = String.valueOf(((IMAPFolder) folder).getUID(messages[i]));
}else {
uid = ((POP3Folder)folder).getUID(messages[i]);
}
//这里会报错
messages[i].getSubject();
log.info("读取第{}封邮件耗时{}ms",i+1,System.currentTimeMillis()-t);
//mailList.add(tran);
}
}
log.info("收取邮件结束,耗时{}ms",System.currentTimeMillis()-t0);
}
当我调用 messages[i].getSubject(); 时,后台报错Failed to load IMAP envelope,断点找到报错位置
这里不知为何没有获取到envelope这个对象,网上找到说法说是邮箱服务器设置了限制,只收取最近30天的邮件,但是我遇到的并不是这个问题。我是先获取了收信箱所有邮件的数量,然后读取最近的cnt封邮件:
//读取索引从from到to的所有邮件
Message[] messages = folder.getMessages(from,n);
当程序在进行第一次读取时,就抛出了异常。
经过一番尝试,我又使用日期范围去进行搜索邮件
// 获取当前日期和30天前的日期
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, -30);
Date thirtyDaysAgo = cal.getTime();
// 创建一个搜索条件,限制邮件日期在30天内
SearchTerm searchTerm = new ReceivedDateTerm(ComparisonTerm.GT, thirtyDaysAgo);
// 使用搜索条件来搜索邮件
Message[] messages = folder.search(searchTerm);
发现这次读取邮件时,并没有报上面的错误,不明觉厉,不明白是什么原因导致的。