java mime multipart javax.mail

Cómo leer el texto dentro del cuerpo del correo usando javax.mail



mime multipart (5)

Estoy desarrollando un correo de cliente usando javax.mail para leer el correo dentro del buzón de correo:

Properties properties = System.getProperties(); properties.setProperty("mail.store.protocol", "imap"); try { Session session = Session.getDefaultInstance(properties, null); Store store = session.getStore("pop3");//create store instance store.connect("pop3.domain.it", "mail.it", "*****"); Folder inbox = store.getFolder("inbox"); FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false); inbox.open(Folder.READ_ONLY);//set access type of Inbox Message messages[] = inbox.search(ft); String mail,sub,bodyText=""; Object body; for(Message message:messages) { mail = message.getFrom()[0].toString(); sub = message.getSubject(); body = message.getContent(); //bodyText = body..... } } catch (Exception e) { System.out.println(e); }

Sé que el método getContent() devuelve un objeto porque el contenido podría ser un String , un MimeMultiPart , un SharedByteArrayInputstream y otro (creo) ... ¿Hay alguna forma de obtener siempre el texto dentro del cuerpo del mensaje? ¡¡Gracias!!


A continuación se muestra el método que toma el texto del mensaje en caso de que bodyParts sea texto y html.

import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.internet.MimeMultipart; import org.jsoup.Jsoup; .... private String getTextFromMessage(Message message) throws Exception { if (message.isMimeType("text/plain")){ return message.getContent().toString(); }else if (message.isMimeType("multipart/*")) { String result = ""; MimeMultipart mimeMultipart = (MimeMultipart)message.getContent(); int count = mimeMultipart.getCount(); for (int i = 0; i < count; i ++){ BodyPart bodyPart = mimeMultipart.getBodyPart(i); if (bodyPart.isMimeType("text/plain")){ result = result + "/n" + bodyPart.getContent(); break; //without break same text appears twice in my tests } else if (bodyPart.isMimeType("text/html")){ String html = (String) bodyPart.getContent(); result = result + "/n" + Jsoup.parse(html).text(); } } return result; } return ""; }

Actualizar Hay un caso, que bodyPart en sí puede ser de tipo multipart. (Me encontré con dicho correo electrónico después de haber escrito esta respuesta). En este caso, necesitará reescribir el método anterior con recursión.


Esta respuesta extiende la respuesta de yurin . El problema que mencionó fue que el contenido de un MimeMultipart puede ser otro MimeMultipart . El método getTextFromMimeMultipart() siguiente se repite en tales casos en el contenido hasta que el cuerpo del mensaje se haya analizado por completo.

private String getTextFromMessage(Message message) throws MessagingException, IOException { String result = ""; if (message.isMimeType("text/plain")) { result = message.getContent().toString(); } else if (message.isMimeType("multipart/*")) { MimeMultipart mimeMultipart = (MimeMultipart) message.getContent(); result = getTextFromMimeMultipart(mimeMultipart); } return result; } private String getTextFromMimeMultipart( MimeMultipart mimeMultipart) throws MessagingException, IOException{ String result = ""; int count = mimeMultipart.getCount(); for (int i = 0; i < count; i++) { BodyPart bodyPart = mimeMultipart.getBodyPart(i); if (bodyPart.isMimeType("text/plain")) { result = result + "/n" + bodyPart.getContent(); break; // without break same text appears twice in my tests } else if (bodyPart.isMimeType("text/html")) { String html = (String) bodyPart.getContent(); result = result + "/n" + org.jsoup.Jsoup.parse(html).text(); } else if (bodyPart.getContent() instanceof MimeMultipart){ result = result + getTextFromMimeMultipart((MimeMultipart)bodyPart.getContent()); } } return result; }


Esta respuesta extiende la respuesta de Austin para corregir el problema original con el tratamiento de multipart/alternative ( // without break same text appears twice in my tests ).

El texto aparece dos veces porque para multipart/alternative , se espera que el agente de usuario elija solo una parte.

Desde RFC2046 :

El tipo "multipart / alternative" es sintácticamente idéntico a "multipart / mixed", pero la semántica es diferente. En particular, cada una de las partes del cuerpo es una versión "alternativa" de la misma información.

Los sistemas deben reconocer que el contenido de las distintas partes es intercambiable. Los sistemas deben elegir el "mejor" tipo según el entorno local y las referencias, en algunos casos incluso a través de la interacción del usuario. Al igual que con "multiparte / mixto", el orden de las partes del cuerpo es significativo. En este caso, las alternativas aparecen en un orden de fidelidad creciente al contenido original. En general, la mejor opción es la última parte de un tipo compatible con el entorno local del sistema del destinatario.

Mismo ejemplo con tratamiento para alternativas:

private String getTextFromMessage(Message message) throws IOException, MessagingException { String result = ""; if (message.isMimeType("text/plain")) { result = message.getContent().toString(); } else if (message.isMimeType("multipart/*")) { MimeMultipart mimeMultipart = (MimeMultipart) message.getContent(); result = getTextFromMimeMultipart(mimeMultipart); } return result; } private String getTextFromMimeMultipart( MimeMultipart mimeMultipart) throws IOException, MessagingException { int count = mimeMultipart.getCount(); if (count == 0) throw new MessagingException("Multipart with no body parts not supported."); boolean multipartAlt = new ContentType(mimeMultipart.getContentType()).match("multipart/alternative"); if (multipartAlt) // alternatives appear in an order of increasing // faithfulness to the original content. Customize as req''d. return getTextFromBodyPart(mimeMultipart.getBodyPart(count - 1)); String result = ""; for (int i = 0; i < count; i++) { BodyPart bodyPart = mimeMultipart.getBodyPart(i); result += getTextFromBodyPart(bodyPart); } return result; } private String getTextFromBodyPart( BodyPart bodyPart) throws IOException, MessagingException { String result = ""; if (bodyPart.isMimeType("text/plain")) { result = (String) bodyPart.getContent(); } else if (bodyPart.isMimeType("text/html")) { String html = (String) bodyPart.getContent(); result = org.jsoup.Jsoup.parse(html).text(); } else if (bodyPart.getContent() instanceof MimeMultipart){ result = getTextFromMimeMultipart((MimeMultipart)bodyPart.getContent()); } return result; }

Tenga en cuenta que este es un ejemplo muy simple. Se pierde muchos casos y no debe utilizarse en la producción en su formato actual.


No lo creo, de lo contrario, ¿qué pasaría si el tipo mime de una Part es image/jpeg ? La API devuelve un Object porque internamente intenta darle algo útil, siempre que sepa qué se espera que sea. Para software de propósito general, está diseñado para ser usado de esta manera:

if (part.isMimeType("text/plain")) { ... } else if (part.isMimeType("multipart/*")) { ... } else if (part.isMimeType("message/rfc822")) { ... } else { ... }

También tiene el Part.getInputStream() Raw (en realidad no es tan Part.getInputStream() , vea Javadoc Part.getInputStream() , pero creo que no es seguro asumir que todos y cada uno de los mensajes que recibe están basados ​​en texto, a menos que esté escribiendo una aplicación muy específica y usted tiene control sobre la fuente de entrada.


Si desea obtener texto siempre, puede omitir otros tipos como ''multiparte'', etc.

Object body = message.getContent(); if(body instanceof String){ // hey it''s a text }