2011-01-18 17 views
7

Ho un'applicazione che viene utilizzata per archiviare i messaggi di posta elettronica usando imap. Anche in questa applicazione ci sono molti account imap che devono essere archiviati.Come scaricare solo nuove email da imap?

In questo momento di volta in volta l'applicazione si collega agli account imap e scarica solo nuove e-mail. Il mio problema è che ogni volta che si connette a un account imap verifica tutte le email da tutte le cartelle e scarica solo le email che non sono ancora state scaricate (memorizzo Message-ID per tutte le email e scarichi solo le email che hanno un ID messaggio che non è memorizzato). Quindi voglio sapere se c'è un'alternativa per questo, perché ci vuole del tempo per verificare tutte le e-mail (per 10-20K ci vogliono 2-5 minuti).

Uso l'API JavaMail per connettersi agli account imap.

risposta

6

Il javadoc aiuta:

IMAPFolder fornisce i metodi:

getMessagesByUID (lungo inizio, fine a lungo) e

getuid (messaggio Messaggio)

Con getuid() si può ottenere l'UID dell'ultimo messaggio che hai già scaricato. Con getMessagesByUID puoi definire questo ultimo messaggio che hai scaricato come start-range e guardare con il metodo getUIDNext() per trovare l'ultimo messaggio che sarebbe la fine dell'intervallo.

+0

Non è una soluzione per me perché gli UID sono cambiati nel tempo, questo è il motivo per cui utilizzo Message-ID per tenere traccia delle e-mail scaricate. – telebog

+0

come ho capito il metodo getUID (messaggio messaggio), è possibile ottenere il MessageUID effettivo per il messaggio specificato dal server. Quindi sarebbe possibile ottenere l'UID effettivo dell'ultimo messaggio che hai e quindi usare i metodi getUIDNext() e getMessagesByUID() per trovare l'ultimo messaggio e scaricare l'intervallo specificato. – Erik

+2

Un UID messaggio cambierà quando il messaggio viene spostato da una cartella (o "mailbox", nella terminologia IMAP) a un'altra. ["Gli identificatori univoci sono assegnati in modo strettamente crescente nella cassetta postale, poiché ogni messaggio viene aggiunto alla cassetta postale a cui è assegnato un UID più alto rispetto al messaggio/i che sono stati aggiunti in precedenza."] (Http: //tools.ietf .org/html/rfc3501 # section-2.3.1.1) telebog sembra voler scaricare ogni messaggio esattamente una volta, indipendentemente dalla cartella in cui si trova. – dkarp

3

controllo solo le intestazioni e quando si raggiunge una nota (l'ultima nota), tirare fuori dai guai:

per esempio (mi sento più bella oggi) e questa è una eccezione dal codice di produzione reale (alcune parti sono state tagliate, quindi potrebbe non compilare, state.processed è un po 'impostato preferibilmente LinkedHashMap surrogata [keySet()] (e w/some max removeEldestEntry booleano confine())

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

Questo è un po 'rischioso, poiché una grande mossa di messaggi noti in cima a un gruppo di nuovi messaggi ti farà perdere quelle nuove. – dkarp

+0

vero questo, è un buon punto; il codice è per leggere messaggi non riusciti, quindi credo che non sia mai stato un problema, di per sé. Il codice dovrebbe mantenere almeno il conteggio precedente e tentare di recuperare almeno molti messaggi indietro. – bestsss

1

filtro sulla bandiera VISTO. Questo flag è destinato trovare nuovi messaggi: l'unico avvertimento è che se il tuo utente utilizza più lettori, potrebbe essere stato visto utilizzando un altro lettore

+1

Intendi il flag "RECENT". E sì, qualsiasi altra connessione del client a quella cartella disattiverà 'RECENT' su tutti i messaggi nella cartella. – dkarp

+0

L'ho visto documentato come SEEN, ma potrebbe essere RECENTE nella tua implementazione. IMAP tiene traccia dei messaggi che non sono ancora stati letti da un client. Per un'interfaccia di un lettore, mi aspetterei che qualsiasi cosa legga con qualsiasi client venga contrassegnata come letta nella mia interfaccia. Il mio background in questo caso è più nella gestione di un server che nella programmazione di un client. – BillThor

+0

Il flag Visto è una bandiera standard. Java contrassegna automaticamente un messaggio come visto quando viene recuperato. Questo è il comportamento che mi aspetto da tutti i clienti. È possibile cancellare la bandiera. – BillThor

0

messaggio-Id che viene fornito come parte dell'intestazione è sempre univoco anche se lo si imposta manualmente. L'ho provato con gamil e racksoace.

+0

Ma non è richiesto e facile è completamente assente. Anche su Gmail. – Hubbitus

Problemi correlati