2011-01-18 18 views
7

私はimapを使って電子メールをアーカイブするのに使われるアプリケーションを持っています。また、このアプリケーションでは、アーカイブする必要がある多くのimapアカウントがあります。imapから新しいメールのみをダウンロードするには?

この瞬間から、アプリケーションはimapアカウントに接続し、新しいメールのみをダウンロードします。私の問題は、IMAPアカウントに接続するたびに、すべてのフォルダのすべての電子メールを確認し、まだダウンロードされていない電子メールのみをダウンロードすることです(すべての電子メールのMessage-IDを保存し、保存されません)。 だから私は、これに代わる方法があるかどうかを知りたいのです。すべての電子メールを検証するのに(10〜20Kの場合は2〜5分かかります)時間がかかるからです。

私はJavaMail APIを使用してimapアカウントに接続します。

答えて

6

javadocができます:

IMAPFolderは、メソッドを提供します。

getMessagesByUID GETUIDで(長い開始、長い方の端)と

GETUID(メッセージメッセージ)

()あなたが得ることができます既にダウンロードした最後のメッセージのUID。 getMessagesByUIDを使用すると、ダウンロードしたこの最後のメッセージを開始範囲として定義し、getUIDNext()メソッドを使用して範囲の最後となる最後のメッセージを検索できます。

+0

UIDが時間の経過とともに変更されるため、解決策ではありません。そのため、ダウンロードした電子メールを追跡するためにMessage-IDを使用しています。 – telebog

+0

私はgetUID(メッセージメッセージ)メソッドを理解しているので、サーバーからの特定のメッセージの実際のMessageUIDを取得できます。したがって、最後に取得したメッセージの実際のUIDを取得し、getUIDNext()メソッドとgetMessagesByUID()メソッドを使用して最後のメッセージを探し、指定された範囲をダウンロードすることが可能です。 – Erik

+2

メッセージUIDは、メッセージをあるフォルダ(またはIMAP用語では「メールボックス」)から別のフォルダに移動すると変更されます。 ["ユニークな識別子はメールボックスで厳密に昇順に割り当てられ、各メッセージはメールボックスに追加されるため、以前に追加されたメッセージよりも高いUIDが割り当てられます。"](http://tools.ietf .org/html/rfc3501#section-2.3.1.1)telebogは、どのフォルダにあるかにかかわらず、各メッセージを正確に1回だけダウンロードしたいようです。 – dkarp

3

ヘッダだけのチェックとあなたが知られているに達した(最後の既知)、救済:

を例えば(私は今日の余分な素敵な感じ)、それは、実際の生産コード(いくつかの部分がカットされたから除きますそれがコンパイルされない可能性があり、いくつかができれ設定されているstate.processedのLinkedHashMapサロゲート[キーセットは()](およびいくつかの最大境界ブーリアンremoveEldestEntry /()w)のSEENフラグに

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

これはちょっとうんざりしています。新しいメッセージの上に既知のメッセージが大きく移動すると、新しいメッセージが表示されなくなります。 – dkarp

+0

それは良い点です。コードは、失敗したメールを読むためのものです。だから、今まで問題ではなかったと思います。コードは、少なくとも以前のカウントを保持し、少なくともその数のメッセージを取得しようとする必要があります。 – bestsss

1

フィルタ。このフラグはのために意図されていますあなたのユーザーが複数のリーダーを使用している場合、別のリーダーを使用している可能性があります。

+1

あなたは 'RECENT'フラグを意味します。そして、ええ、そのフォルダへの他のクライアントの接続は、フォルダ内のすべてのメッセージで 'RECENT'を解除します。 – dkarp

+0

私はそれがSEENとして文書化されているのを見ましたが、あなたの実装ではRECENTであるかもしれません。 IMAPは、まだクライアントによって読み取られていないメッセージを追跡します。読者インターフェイスの場合、私は、私のインターフェイスで読まれたマークが付いたクライアントで読んだものはどれも期待します。この場合の私の背景は、クライアントをプログラミングするよりもサーバーを管理することです。 – BillThor

+0

Seenフラグは標準フラグです。 Javaは、メッセージが取得されたときに表示されるメッセージに自動的にフラグを立てます。これはすべてのクライアントから期待される動作です。フラグをクリアすることは可能です。 – BillThor

0

メッセージのヘッダの一部として入っているIdは、手動で設定しても常にユニークです。iは、gamilとracksoaceでテストしました。

+0

しかし、それは必須ではなく、簡単にはありません。 Gmailでも。 – Hubbitus

関連する問題