栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

通过SSL的JavaMail IMAP速度非常慢-批量提取多条消息

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

通过SSL的JavaMail IMAP速度非常慢-批量提取多条消息

经过大量工作和JavaMail员工的帮助,这种“缓慢”的来源来自API中的FETCH行为。确实,正如pjaol所说,每次需要消息的信息(标头或消息内容)时,我们都会返回服务器。

如果FetchProfile允许我们批量获取许多消息的标头信息或标志,则无法直接获取多个消息的内容。

幸运的是,我们可以编写自己的IMAP命令来避免这种“局限性”(这样做是为了避免出现内存不足错误:在一个命令中提取内存中的每个邮件可能会很繁重)。

这是我的代码:

import com.sun.mail.iap.Argument;import com.sun.mail.iap.ProtocolException;import com.sun.mail.iap.Response;import com.sun.mail.imap.IMAPFolder;import com.sun.mail.imap.protocol.BODY;import com.sun.mail.imap.protocol.FetchResponse;import com.sun.mail.imap.protocol.IMAPProtocol;import com.sun.mail.imap.protocol.UID;public class CustomProtocolCommand implements IMAPFolder.ProtocolCommand {        int start;        int end;    public CustomProtocolCommand(int start, int end) {        this.start = start;        this.end = end;    }    @Override    public Object doCommand(IMAPProtocol protocol) throws ProtocolException {        Argument args = new Argument();        args.writeString(Integer.toString(start) + ":" + Integer.toString(end));        args.writeString("BODY[]");        Response[] r = protocol.command("FETCH", args);        Response response = r[r.length - 1];        if (response.isOK()) { Properties props = new Properties(); props.setProperty("mail.store.protocol", "imap"); props.setProperty("mail.mime.base64.ignoreerrors", "true"); props.setProperty("mail.imap.partialfetch", "false"); props.setProperty("mail.imaps.partialfetch", "false"); Session session = Session.getInstance(props, null); FetchResponse fetch; BODY body; MimeMessage mm; ByteArrayInputStream is = null; // last response is only result summary: not contents for (int i = 0; i < r.length - 1; i++) {     if (r[i] instanceof IMAPResponse) {         fetch = (FetchResponse) r[i];         body = (BODY) fetch.getItem(0);         is = body.getByteArrayInputStream();         try {  mm = new MimeMessage(session, is);  Contents.getContents(mm, i);         } catch (MessagingException e) {  e.printStackTrace();         }     } }        }        // dispatch remaining untagged responses        protocol.notifyResponseHandlers(r);        protocol.handleResult(response);        return "" + (r.length - 1);    }}

getContents(MimeMessage mm,int i)函数是一个经典函数,该函数以递归方式将消息的内容打印到文件中(网上有许多示例)。

为了避免出现内存不足错误,我只需设置maxDocs和maxSize限制(这是任意完成的,可能可以改进!),其用法如下:

public int efficientGetContents(IMAPFolder inbox, Message[] messages)        throws MessagingException {    FetchProfile fp = new FetchProfile();    fp.add(FetchProfile.Item.FLAGS);    fp.add(FetchProfile.Item.ENVELOPE);    inbox.fetch(messages, fp);    int index = 0;    int nbMessages = messages.length;    final int maxDoc = 5000;    final long maxSize = 100000000; // 100Mo    // Message numbers limit to fetch    int start;    int end;    while (index < nbMessages) {        start = messages[index].getMessageNumber();        int docs = 0;        int totalSize = 0;        boolean noskip = true; // There are no jumps in the message numbers          // list        boolean notend = true;        // Until we reach one of the limits        while (docs < maxDoc && totalSize < maxSize && noskip && notend) { docs++; totalSize += messages[index].getSize(); index++; if (notend = (index < nbMessages)) {     noskip = (messages[index - 1].getMessageNumber() + 1 == messages[index]  .getMessageNumber()); }        }        end = messages[index - 1].getMessageNumber();        inbox.doCommand(new CustomProtocolCommand(start, end));        System.out.println("Fetching contents for " + start + ":" + end);        System.out.println("Size fetched = " + (totalSize / 1000000)     + " Mo");    }    return nbMessages;}

在此不要使用我所使用的消息号,它是不稳定的(如果从服务器中删除了消息,则这些更改)。更好的方法是使用UID!然后,将命令从FETCH更改为UID
FETCH。

希望这会有所帮助!



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/418625.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号