繁体   English   中英

从javamail读取需要很长时间

[英]Reading from javamail takes a long time

我使用 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)。 阅读 13Mb 邮件的时间从 51-55 分钟降低到阅读相同邮件的 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。 这将使小消息更快,大消息更有效率。

我有一个类似的问题。 通过 IMAP 获取邮件非常慢。 此外,我在下载大附件时遇到了另一个问题。 在查看JavaMail 常见问题解答后,我找到了此问题中后面问题的解决方案,该解决方案建议将mail.imap.partialfetch (分别为mail.imaps.partialfetch )设置为false 这不仅解决了下载问题,还解决了消息读取缓慢的问题。

在引用的 JavaMail notes.txt 中是这样说的。

  1. 由于 Microsoft Exchange IMAP 服务器中的问题,读取大邮件时可能检索到的字节数不足。 有两种方法可以解决此 Exchange 错误:

    (a) Exchange IMAP 服务器向 UI 提供称为“快速消息检索”的配置选项。 只需转到站点、服务器或收件人,单击“IMAP4”选项卡,其中一个复选框是“启用快速消息检索”。 关闭它,八位字节计数将是准确的。 这在http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q191504 中有完整描述

    (b) 将“mail.imap.partialfetch”属性设置为false。 您必须在提供给会话的 Properties 对象中设置此属性。

  2. 某些 IMAP 服务器没有正确实现 IMAP Partial FETCH 功能。 从 IMAP 服务器下载大邮件时,此问题通常表现为电子邮件附件损坏。 要解决此服务器错误,请将“mail.imap.partialfetch”属性设置为 false。 您必须在提供给会话的 Properties 对象中设置此属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM