Q:

How to download only new emails from imap?

I have an application that is used to archive emails using imap. Also in this application are many imap accounts that need to be archived.
In this moment from time to time the application connects to imap accounts and download only new emails. My issue is that every time when it connects to an imap account it verifies all emails from all folders and downloads only emails that aren't downloaded yet (I store Message-ID for all emails and download only emails that have an Message-ID that is not stored).
So I want to know if there is an alternative for this, because it takes some time to verify all emails (for 10-20K it takes 2-5 minutes).
I use JavaMail API to connect to imap accounts.

A:

The javadoc helps:
IMAPFolder provides the methods:
getMessagesByUID(long start, long end) and
getUID(Message message)
With getUID() you can get the UID of the last message you already have downloaded. With getMessagesByUID you can define this last message you have downloaded as start-range and look with the method getUIDNext() to find the last message which would be the end of the range.

A:

check only the headers and when you reach a known (the last known), bail out:
for instance (i feel extra nice today) and that's an except from real production code (some parts were cut, so it might not compile, state.processed is some set preferrably LinkedHashMap surrogate [keySet()] (and w/ some max boundary  boolean removeEldestEntry())
 try {
      store = mailSession.getStore("imap");
      try {
        store.connect();
        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_ONLY);

        int count = folder.getMessageCount();
        for(int localProc=0, chunk=49;localProc<10 && count>0; count -=chunk+1){

          Message messages[] = folder.getMessages(Math.max(count-chunk, 1), count);

          FetchProfile fp = new FetchProfile();
          fp.add(FetchProfile.Item.ENVELOPE);
          fp.add("Message-ID");
//add more headers, if need be
          folder.fetch(messages,fp);

          for (int i=messages.length;--i>=0;) {

            //can check abort request here
            Message  message = messages[i];

            String msgId = getHeader(message,"Message-ID");
            if (msgId!=null && !state.processed.add(msgId)){            
              if (++localProc>=10){
                break;
              }
              continue;
            }
///process here, catch exception, etc..
          }
        }

        folder.close(false);        
      } catch (MessagingException e) {
        logger.log(Level.SEVERE, "Mail messaging exception", e);
      }
    } catch (NoSuchProviderException e) {
      logger.log(Level.SEVERE, "No mail provider", e);
    }

    if(store != null) {
      try {
        store.close();
      } catch (MessagingException e) {}
    }

