2009-11-17 20 views
89

Ahora que `he descargado todos los mensajes y almacenarlos adescargar archivos utilizando Java Mail

Message[] temp; 

¿Cómo puedo obtener la lista de archivos adjuntos para cada uno de esos mensajes a

List<File> attachments; 

Nota: no hay librerías de terceros, solo JavaMail.

+4

Esta fue una pregunta muy útil para mí, ¡merece más votos! Gracias por preguntarlo. – Yottagray

Respuesta

91

Sin manejo de excepciones, pero aquí va:

List<File> attachments = new ArrayList<File>(); 
for (Message message : temp) { 
    Multipart multipart = (Multipart) message.getContent(); 

    for (int i = 0; i < multipart.getCount(); i++) { 
     BodyPart bodyPart = multipart.getBodyPart(i); 
     if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) && 
       StringUtils.isBlank(bodyPart.getFileName())) { 
      continue; // dealing with attachments only 
     } 
     InputStream is = bodyPart.getInputStream(); 
     File f = new File("/tmp/" + bodyPart.getFileName()); 
     FileOutputStream fos = new FileOutputStream(f); 
     byte[] buf = new byte[4096]; 
     int bytesRead; 
     while((bytesRead = is.read(buf))!=-1) { 
      fos.write(buf, 0, bytesRead); 
     } 
     fos.close(); 
     attachments.add(f); 
    } 
} 
+2

Pero espere un minuto, ¿no se supone que debemos verificar si (bodyPart.getDisposition() == Part.ATTACHMENT) {} antes de guardar el archivo, para que no se guarde el cuerpo del correo electrónico? – folone

+2

Tiene razón, he corregido el código –

+7

¿No sería más natural de leer que StringUtils.isBlank() que utilizando! StringUtils.isNotBlank? – Kuchi

23

pregunta es muy antiguo, pero tal vez ayude a alguien. Me gustaría expandir la respuesta de David Rabinowitz.

if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) 

no debe devolver todos los archivos adjuntos como usted espera, porque puede tener un correo donde la parte mixta no tiene una disposición definida.

----boundary_328630_1e15ac03-e817-4763-af99-d4b23cfdb600 
Content-Type: application/octet-stream; 
    name="00000000009661222736_236225959_20130731-7.txt" 
Content-Transfer-Encoding: base64 

así que en este caso, también puede verificar el nombre del archivo. De esta manera:

if (!Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) && StringUtils.isBlank(part.getFileName())) {...} 

EDITAR

hay código de trabajo entera usando condición descibed anteriormente .. Debido a que cada parte puede encapsular otras partes y de fijación debe estar anidado en, recursión se usa para recorrer a través de todas las partes

public List<InputStream> getAttachments(Message message) throws Exception { 
    Object content = message.getContent(); 
    if (content instanceof String) 
     return null;   

    if (content instanceof Multipart) { 
     Multipart multipart = (Multipart) content; 
     List<InputStream> result = new ArrayList<InputStream>(); 

     for (int i = 0; i < multipart.getCount(); i++) { 
      result.addAll(getAttachments(multipart.getBodyPart(i))); 
     } 
     return result; 

    } 
    return null; 
} 

private List<InputStream> getAttachments(BodyPart part) throws Exception { 
    List<InputStream> result = new ArrayList<InputStream>(); 
    Object content = part.getContent(); 
    if (content instanceof InputStream || content instanceof String) { 
     if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) || StringUtils.isNotBlank(part.getFileName())) { 
      result.add(part.getInputStream()); 
      return result; 
     } else { 
      return new ArrayList<InputStream>(); 
     } 
    } 

    if (content instanceof Multipart) { 
      Multipart multipart = (Multipart) content; 
      for (int i = 0; i < multipart.getCount(); i++) { 
       BodyPart bodyPart = multipart.getBodyPart(i); 
       result.addAll(getAttachments(bodyPart)); 
      } 
    } 
    return result; 
} 
+0

la expresión comprueba el nombre de archivo vacío o 'nulo'. ¿Es eso correcto? – Keerthivasan

+0

Pulpo: Sí. Comprueba si una CharSequence no está vacía (""), no es nula y no solo en espacios en blanco. – mefi

+0

¿Puede decirnos cómo convertir la lista en la lista ? – kumuda

9

Algunos ahorro de tiempo para el código donde se guarda el archivo adjunto:

con la versión 1.4 de correo javax y después, se puede decir

bodyPart.saveFile("/tmp/" + bodyPart.getFileName()); 

en lugar de

InputStream is = bodyPart.getInputStream(); 
    File f = new File("/tmp/" + bodyPart.getFileName()); 
    FileOutputStream fos = new FileOutputStream(f); 
    byte[] buf = new byte[4096]; 
    int bytesRead; 
    while((bytesRead = is.read(buf))!=-1) { 
     fos.write(buf, 0, bytesRead); 
    } 
    fos.close(); 
+3

[Aparentemente] (http://docs.oracle.com/javaee /6/api/javax/mail/internet/MimeBodyPart.html#saveFile(java.lang.String)) 'bodyPart' se debe convertir primero a' MimeBodyPart', como por ejemplo: '((MimeBodyPart) bodyPart) .saveFile ("/tmp/"+ bodyPart.getFileName());' – yair

0

Aquí está mi interpretación de mefi's solution.

private static void attachments(
    final BodyPart body, final BiConsumer<String, InputStream> consumer) 
    throws MessagingException, IOException { 
    final Multipart content; 
    try { 
     content = (Multipart) body.getContent(); 
     for (int i = 0; i < content.getCount(); i++) { 
      attachments(content.getBodyPart(i), consumer); 
     } 
     return; 
    } catch (final ClassCastException cce) { 
    } 
    if (!Part.ATTACHMENT.equalsIgnoreCase(body.getDisposition())) { 
     return; 
    } 
    final String name = body.getFileName(); 
    if (name == null || name.trim().isEmpty()) { 
     return; 
    } 
    try (final InputStream stream = body.getInputStream()) { 
     consumer.accept(name, stream); 
    } 
} 

public static void attachments(
    final Message message, final BiConsumer<String, InputStream> consumer) 
    throws IOException, MessagingException { 
    final Multipart content; 
    try { 
     content = (Multipart) message.getContent(); 
    } catch (final ClassCastException cce) { 
     return; 
    } 
    for (int i = 0; i < content.getCount(); i++) { 
     attachments(content.getBodyPart(i), consumer); 
    } 
} 
2

Usted puede simplemente utilizar Apache Commons correo API MimeMessageParser - getAttachmentList() a lo largo de los Comunes IO y Commons Lang.

MimeMessageParser parser = .... 
parser.parse(); 
for(DataSource dataSource : parser.getAttachmentList()) { 

    if (StringUtils.isNotBlank(dataSource.getName())) {} 

     //use apache commons IOUtils to save attachments 
     IOUtils.copy(dataSource.getInputStream(), ..dataSource.getName()...) 
    } else { 
     //handle how you would want attachments without file names 
     //ex. mails within emails have no file name 
    } 
} 
Cuestiones relacionadas