2011-01-18 10 views
7

Tengo una aplicación que se usa para archivar correos electrónicos usando imap. También en esta aplicación hay muchas cuentas imap que necesitan ser archivadas.¿Cómo descargar solo nuevos correos electrónicos de imap?

En este momento, de vez en cuando, la aplicación se conecta a cuentas imap y descarga solo correos electrónicos nuevos. Mi problema es que cada vez que se conecta a una cuenta imap, verifica todos los correos electrónicos de todas las carpetas y solo descarga correos electrónicos que aún no se descargan (almaceno Message-ID para todos los correos electrónicos y descargo solo correos electrónicos que tienen un ID de mensaje que no está almacenado). Así que quiero saber si hay una alternativa para esto, ya que lleva algo de tiempo verificar todos los correos electrónicos (para 10-20K lleva de 2 a 5 minutos).

Uso JavaMail API para conectarme a las cuentas de imap.

Respuesta

6

El javadoc ayuda:

IMAPFolder proporciona los métodos:

getMessagesByUID (inicio de largo, largo final) y

getuid (mensaje Mensaje)

Con getuid() se puede obtener el UID del último mensaje que ya ha descargado. Con getMessagesByUID puede definir este último mensaje que ha descargado como rango de inicio y buscar con el método getUIDNext() para encontrar el último mensaje que sería el final del rango.

+0

No es una solución para mí porque los UID han cambiado con el tiempo, es por eso que uso Message-ID para rastrear correos descargados. – telebog

+0

según entiendo el método getUID (Message message), puede obtener el MessageUID real para el mensaje dado del servidor. Entonces sería posible obtener el UID real del último mensaje que tienes y luego usar los métodos getUIDNext() y getMessagesByUID() para encontrar el último mensaje y descargar el rango dado. – Erik

+2

Un mensaje UID cambiará cuando el mensaje se mueva de una carpeta (o "buzón", en terminología IMAP) a otra. ["Los identificadores únicos se asignan de manera estrictamente ascendente en el buzón, ya que cada mensaje se agrega al buzón se le asigna un UID más alto que el mensaje (s) que se agregaron previamente."] (Http: //tools.ietf .org/html/rfc3501 # section-2.3.1.1) telebog parece querer descargar cada mensaje exactamente una vez, independientemente de la carpeta en la que se encuentre. – dkarp

3

cheque sólo los encabezados y cuando se llega a un conocido (la última conocida), rescatar a:

por ejemplo (me siento extraordinariamente bien hoy) y eso es una excepción a partir del código de producción real (se cortaron algunas partes, lo que no podría compilar, state.processed se algún conjunto preferiblemente LinkedHashMap sustituto [conjunto de claves()] (y w/algunos removeEldestEntry boolean límite max())

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

Esto es un poco arriesgado, ya que un gran movimiento de mensajes conocidos además de un montón de mensajes nuevos hará que te pierdas los nuevos. – dkarp

+0

cierto eso, es un buen punto; el código es para leer correos fallidos, así que supongo que nunca ha sido un problema, en sí mismo. El código debe mantener al menos el conteo anterior e intentar recuperar al menos esa cantidad de mensajes. – bestsss

1

filtro en la bandera visto. Esta bandera está destinado a encontrar nuevos mensajes. La única advertencia es que si su usuario está usando múltiples lectores, entonces puede haber sido visto usando otro lector.

+1

Te refieres a la bandera 'RECIENTE '. Y sí, la conexión de cualquier otro cliente a esa carpeta desactivará 'RECIENTE' en todos los mensajes de la carpeta. – dkarp

+0

Lo he visto documentado como VISTO, pero puede ser RECIENTE en su implementación. IMAP realiza un seguimiento de los mensajes que aún no han sido leídos por un cliente. Para una interfaz de lector, esperaría que todo lo que lea con cualquier cliente se marque como leído en mi interfaz. Mi experiencia en este caso es más en la administración de un servidor que en la programación de un cliente. – BillThor

+0

La bandera vista es una bandera estándar. Java marcará automáticamente un mensaje como se ve cuando se recupera. Este es el comportamiento que espero de todos los clientes. Es posible borrar la bandera. – BillThor

0

message-Id que viene como parte del encabezado es siempre único, incluso si lo configura manualmente. Lo he probado con gamil y racksoace.

+0

Pero no es necesario y fácil y no está ausente. En Gmail también. – Hubbitus

Cuestiones relacionadas