How to download only new emails from imap?

2019-04-26 21:32发布

问题:

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.

回答1:

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.



回答2:

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) {}
    }


回答3:

Filter on the SEEN flag. This flag is intended for finding new messages. The one Caveat is that if your user is using multiple readers, then it may have been seen using another reader.



回答4:

message-Id which comes as part of the header is always unique even if u set it manually .i have tested it with gamil and racksoace.