Solución:
Esta respuesta extiende la respuesta de Yurin. La cuestión que planteó fue que el contenido de un MimeMultipart
puede ser en sí mismo otro MimeMultipart
. los getTextFromMimeMultipart()
El método 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 amplía 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 uno parte.
Desde RFC2046:
El tipo “multiparte / alternativo” es sintácticamente idéntico a “multiparte / 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 en función del 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 receptor.
Mismo ejemplo con el tratamiento por 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. Pasa por alto muchos casos y no debe usarse en producción en su formato actual.
¡No reinventes la rueda! Simplemente puede usar Apache Commons Email (ver aquí)
Ejemplo de Kotlin:
fun readHtmlContent(message: MimeMessage) =
MimeMessageParser(message).parse().htmlContent
Si el correo electrónico no tiene contenido html, pero tiene contenido simple (puede verificarlo con los métodos hasPlainContent y hasHtmlContent), entonces debe usar este código:
fun readPlainContent(message: MimeMessage) =
MimeMessageParser(message).parse().plainContent
Ejemplo de Java:
String readHtmlContent(MimeMessage message) throws Exception {
return new MimeMessageParser(message).parse().getHtmlContent();
}
String readPlainContent(MimeMessage message) throws Exception {
return new MimeMessageParser(message).parse().getPlainContent();
}