Casey B.
Casey B.

Reputation: 279

Speed up email retrieval with JavaMail

Currently my code accesses my Gmail inbox with IMAP (imaps) and JavaMail, for the purpose of reading emails sent to myself from newest to oldest, identifying which ones have attachments in the .zip or .xap format. If found, the email's subject is displayed and asks if I want to download the attachment.

If I click no, it continues searching. If I click yes, it calls the createFolder method to create a directory, saves the attachment there, and then extracts it.

Problem: The most recent email in my inbox has a .zip file so it is quickly found, but if I click "No" it takes upwards of 20 seconds to find the next email containing a zip/xap for 2 reasons: (1) There are 20+ emails more recent (2) There are 2 emails more recent containing attachments BUT NOT zip/xap.

I'm guessing this is due to the recursion that's occuring to isolate attachments before identifying their format, or some other redundant code/method? I've read here and here that a Fetch Profile can help, instead of contacting the server unnecessarily.

I'm hoping to decrease the delay substantially. Is Fetch/Envelope the way to go? Is my code a tangled mess, or can you share a sample solution? Thank you!

Full Code:

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", "[email protected]", "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("[email protected]")) {
                    //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();
    }
}

Upvotes: 1

Views: 917

Answers (1)

Bill Shannon
Bill Shannon

Reputation: 29971

A FetchProfile allows you to prefetch some of the message information "in bulk". This prefetched information is then used later when you access the corresponding fields of the Message objects. You probably want to use FetchProfile.Item.CONTENT_INFO and FetchProfile.Item.ENVELOPE. Other than that, your code looks fine.

Upvotes: 2

Related Questions