使用 JavaMail 加快电子邮件检索

Speed up email retrieval with JavaMail

目前,我的代码使用 IMAP (imaps) 和 JavaMail 访问我的 Gmail 收件箱,目的是按照从最新到最旧的顺序阅读发送给我自己的电子邮件,识别哪些电子邮件具有 .zip 或 .xap 格式的附件。如果找到,将显示电子邮件的主题并询问我是否要下载附件。

如果我点击否,它会继续搜索。如果我单击是,它会调用 createFolder 方法创建一个目录,将附件保存在那里,然后将其解压缩。

问题: 我收件箱中最近的一封电子邮件有一个 .zip 文件,因此可以很快找到它,但如果我单击 "No" 则需要 20 秒以上的时间查找下一封包含 zip/xap 的电子邮件有两个原因:(1) 最近有 20 多封电子邮件 (2) 最近有 2 封电子邮件包含附件但不包含 zip/xap。

我猜这是由于在识别附件格式之前为了隔离附件而发生的递归,或者其他一些多余的 code/method?我读过 here and here,获取配置文件可以提供帮助,而不是不必要地联系服务器。

我希望大大减少延迟。 Fetch/Envelope 是正确的选择吗?我的代码乱七八糟吗,或者你能分享一个示例解决方案吗?谢谢!

完整代码:

public class ReceiveMailImap {
    public ReceiveMailImap() {}

    public static void doit() throws MessagingException, IOException {
        Folder inbox = null;
        Store store = null;

        try {
            Properties props = System.getProperties();
            Session session = Session.getDefaultInstance(props, null);
            //session.setDebug(true);
            store = session.getStore("imaps");
            store.connect("imap.gmail.com", "myAccount@gmail.com", "myPassword");
            inbox = store.getFolder("Inbox");
            inbox.open(Folder.READ_WRITE);
            Message messages[] = inbox.getMessages();

            //  Loop newest to oldest
            for (int i = messages.length - 1; i >= 0; i--) {
                Message msg = messages[i];
                //If current msg has no attachment, skip.
                if (!hasAttachments(msg)) {
                    continue;
                }

                String from = "Sender Unknown";
                if (msg.getReplyTo().length >= 1) {
                    from = msg.getReplyTo()[0].toString();
                } else if (msg.getFrom().length >= 1) {
                    from = msg.getFrom()[0].toString();
                }
                subject = msg.getSubject();

                if (from.contains("myAccount@gmail.com")) {
                    //Get My Documents

                    subject = subject.replaceAll("[^a-zA-Z0-9.-]", "_");

                    //Call Save Attachment -->>
                    saveAttachment(msg.getContent());
                    msg.setFlag(Flags.Flag.SEEN, true);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (inbox != null) {
                inbox.close(true);
            }
            if (store != null) {
                store.close();
            }
        }
    }

    public static boolean hasAttachments(Message msg) throws MessagingException, IOException {
        if (msg.isMimeType("multipart/mixed")) {
            Multipart mp = (Multipart) msg.getContent();
            if (mp.getCount() > 1) return true;
        }
        return false;
    }

    public static void saveAttachment(Object content)
    throws IOException, MessagingException {
        OutputStream out = null;
        InputStream in = null;
        try {
            if (content instanceof Multipart) {
                Multipart multi = ((Multipart) content);
                int parts = multi.getCount();
                for (int j = 0; j < parts; ++j) {
                    MimeBodyPart part = (MimeBodyPart) multi.getBodyPart(j);
                    if (part.getContent() instanceof Multipart) {
                        // part-within-a-part, do some recursion...
                        saveAttachment(part.getContent());
                    } else {
                        int allow = 0;

                        if (part.isMimeType("application/x-silverlight-app")) {
                            extension = "xap";
                            allow = 1;
                        } else {
                            if (part.isMimeType("application/zip")) {
                                extension = "zip";
                                allow = 1;
                            }
                        }
                        if (allow == 1) {
                            int dialogResult = JOptionPane.showConfirmDialog(null, "The most recent file is: " + subject + " Would you like to download this file?", "Question", 0);
                            if (dialogResult == JOptionPane.YES_OPTION) {
                                savePath = createFolder(subject) + "\" + subject + "." + extension;
                            } else {
                                continue;
                            }
                            out = new FileOutputStream(new File(savePath)); in = part.getInputStream();
                            int k;
                            while ((k = in .read()) != -1) {
                                out.write(k);
                            }

                            //Unzip
                            savePath = savePath.toString();
                            Unzip unzipFile = new Unzip();
                            unzipFile.UnZipper(dir, savePath);
                        } else {
                            continue;
                        }
                    }
                }
            }
        } finally {
            if ( in != null) { in .close();
            }
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

    public static File createFolder(String subject) {
        JFileChooser fr = new JFileChooser();
        FileSystemView myDocs = fr.getFileSystemView();
        String myDocuments = myDocs.getDefaultDirectory().toString();
        dir = new File(myDocuments + "\" + subject);
        savePathNoExtension = dir.toString();
        dir.mkdir();
        return dir;
    }

    public static void main(String args[]) throws Exception {
        ReceiveMailImap.doit();
    }
}

FetchProfile 允许您预取一些消息信息"in bulk"。当您访问 Message 对象的相应字段时,稍后会使用此预取信息。您可能想使用 FetchProfile.Item.CONTENT_INFO and FetchProfile.Item.ENVELOPE。除此之外,您的代码看起来还不错。