从javamail读取需要很长时间

我使用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 // ... } 

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

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

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

解决方案,至少是对我有用的解决方案,可在此站点找到: 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(); // .... } 

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

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

希望这有助于某人并抱歉英语错误;)

它始终是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. 

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

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

使用Folder.fetch方法,您可以在一个操作中预取多个消息的元数据。 这将减少处理每条消息的时间,但对于一条巨大的消息却无济于事。

处理巨大的消息部分有效,您通常希望使用getInputStream方法以递增方式处理数据,而不是使用getContent方法读取所有数据并使用所有数据创建一个巨大的String对象。

您还可以通过指定“mail.imap.fetchsize”属性来调整提取,该属性默认为16384.如果您的大多数消息都小于100K,并且您始终需要读取消息中的所有数据,则可以设置fetchsize到100K。 这将使小消息更快,更大的消息更有效。