java 如何仅从 imap 下载新电子邮件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4725063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:44:11  来源:igfitidea点击:

How to download only new emails from imap?

javaimapjavamail

提问by telebog

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.

我有一个用于使用 imap 归档电子邮件的应用程序。此应用程序中还有许多需要存档的 imap 帐户。

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).

此时,应用程序会不时连接到 imap 帐户并仅下载新电子邮件。我的问题是,每次连接到 imap 帐户时,它都会验证所有文件夹中的所有电子邮件,并仅下载尚未下载的电子邮件(我为所有电子邮件存储 Message-ID,仅下载具有 Message-ID 的电子邮件)不存储)。所以我想知道是否有替代方案,因为验证所有电子邮件需要一些时间(对于 10-20K 需要 2-5 分钟)。

I use JavaMail API to connect to imap accounts.

我使用 JavaMail API 连接到 imap 帐户。

采纳答案by Erik

The javadochelps:

javadoc的帮助:

IMAPFolder provides the methods:

IMAPFolder 提供了以下方法:

getMessagesByUID(long start, long end) and

getMessagesByUID(长开始,长结束)和

getUID(Message message)

getUID(消息消息)

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.

使用 getUID() 可以获取已下载的最后一条消息的 UID。使用 getMessagesByUID,您可以将下载的最后一条消息定义为起始范围,并使用 getUIDNext() 方法查找最后一条消息,即该范围的结束。

回答by bestsss

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())

例如(我今天感觉特别好)这是实际生产代码的一个例外(某些部分被剪切,所以它可能无法编译,state.processed 是一些集合,最好是 LinkedHashMap 代理 [keySet()](和一些最大边界布尔值 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) {}
    }

回答by BillThor

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.

过滤 SEEN 标志。此标志用于查找新消息。一个警告是,如果您的用户使用多个阅读器,那么可能已经使用另一个阅读器看到了它。

回答by vipin

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.

即使您手动设置它,作为标头一部分出现的 message-Id 始终是唯一的。我已经用 gamil 和 racksoace 对其进行了测试。