从javamail读取需要很长时间

Alb*_*ert 5 java jakarta-mail

我使用javamail使用IMAP协议从交易账户中读取邮件.这些邮件是纯文本格式,其内容是XML.

几乎所有这些邮件都有短尺寸(通常低于100Kb).但是,有时我必须处理大邮件(大约10Mb-15Mb).例如,昨天我收到了一封13Mb的电子邮件.只需阅读它就花了50多分钟.这是正常的吗?有没有办法提高其性能?代码是:

Session sesion = Session.getInstance(System.getProperties());
Store store = sesion.getStore("imap");
store.connect(host, user, passwd);
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);

Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
for (int i = 0 ; i< messages.length ; i++){
    Object contents = messages[i].getContent();  // Here it takes 50 min on 13Mb mail
    // ...
}
Run Code Online (Sandbox Code Playgroud)

花费这么长时间的方法是messages[i].getContent().我究竟做错了什么?任何提示?

非常感谢,对不起我的英语!;)

Alb*_*ert 7

我终于解决了这个问题并想分享.

解决方案,至少是对我有用的解决方案,可在此站点找到:http://www.oracle.com/technetwork/java/faq-135477.html#imapserverbug

所以,我在我的第一篇文章中输入的原始代码变为:

Session sesion = Session.getInstance(System.getProperties());
Store store = sesion.getStore("imap");
store.connect(host, user, passwd);
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);

// Convert to MimeMessage after search 
MimeMessage[] messages = (MimeMessage[]) carpetaInbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
for (int i = 0 ; i< messages.length ; i++){
    // Create a new message using MimeMessage copy constructor
    MimeMessage cmsg = new MimeMessage(messages[i]);
    // Use this message to read its contents 
    Object obj = cmsg.getContent(); 
// ....
}
Run Code Online (Sandbox Code Playgroud)

诀窍是,使用MimeMessage()复制构造函数,创建一个新的MimeMessage并读取其内容而不是原始消息.您应该注意,此类对象并未真正连接到服务器,因此您对其所做的任何更改(如设置标志)都不会生效.消息的任何更改都必须在原始消息上完成.

总结:此解决方案可以读取使用IMAP协议连接到Exchange Server的大型纯文本邮件(最多15Mb).时间从51-55分钟降低到读取13Mb邮件,到9秒读取相同邮件.难以置信的.

希望这可以帮助别人并抱歉英语错误;)


ary*_*ann 5

代码中最慢的部分始终是 messages[i].getContent()。原因通常是 IMAP 服务器不会缓存这部分消息数据。不过,你可以试试这个:

    FetchProfile fp = new FetchProfile();
        fp.add(FetchProfile.Item.ENVELOPE);
        fp.add(FetchProfileItem.FLAGS);
        fp.add(FetchProfileItem.CONTENT_INFO);
    fp.add("X-mailer");

and after you have specified the fetch profile then you do your search/fetch of messages. 
Run Code Online (Sandbox Code Playgroud)

基本上这个概念是 IMAP 提供程序仅在必要时从服务器获取消息数据。(javax.mail.FetchProfile 用于对此进行优化)。标头和正文结构信息一旦被获取,就会始终缓存在 Message 对象中。但是,bodypart 的内容不会被缓存。因此,每次客户端请求内容时(使用 getContent() 或使用 getInputStream()),都会向服务器发出新的 FETCH 请求。这样做的原因是一条消息的内容可能很大,如果我们为大量消息缓存这些内容,由于垃圾收集器无法释放引用的消息,系统可能很快就会耗尽内存对象。客户应该意识到这一点,并且在需要时必须自己保留检索到的内容。

通过使用上面提到的代码片段,您可以“希望”提高一些速度,但这完全取决于您的 SMTP 服务器是否可行。由于上一段中提到的负载问题,所有大型 SMTP 服务器都不支持此行为,因此您可能无法获得任何速度。