So lesen Sie Text im E-Mail-Text mit javax.mail

Lesezeit: 8 Minuten

Ich entwickle eine Client-Mail mit javax.mail, um E-Mails im Postfach zu lesen:

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);    
}

Ich kenne die Methode getContent() gibt ein Objekt zurück, weil der Inhalt a sein könnte Stringa MimeMultiParta SharedByteArrayInputstream und andere (glaube ich) … Gibt es eine Möglichkeit, immer den Text in den Nachrichtentext zu bekommen? Vielen Dank!!

  • Was für eine Ausgabe bekommst du??? kannst du nicht nutzen msg.getContentType() zum Identifizieren des Typs und zum Verarbeiten von E-Mails basierend auf dem Typ??

    – Raghav

    28. Juni 2012 um 8:14 Uhr

  • Ich muss nicht wissen, um welche Art von Inhalt es sich handelt, ich muss nur den darin enthaltenen Text kennen

    – Jayyrus

    28. Juni 2012 um 8:16 Uhr

  • Jede Mail mit einem anderen MIME-Typ muss anders behandelt werden, um Text zu erhalten. Sie müssen also mit wechseln getContentType

    – Raghav

    28. Juni 2012 um 8:23 Uhr

  • Hier gibt es eine wirklich seltsame Mischung aus POP3- und IMAP-Sachen.

    – dkarp

    1. August 2012 um 5:18 Uhr


  • Siehe auch stackoverflow.com/questions/5628395/…

    – Kein Name

    1. Oktober 2014 um 14:03 Uhr

Benutzer-Avatar
Austin

Diese Antwort erweitert Yurins Antwort. Das Problem, das er ansprach, war, dass der Inhalt von a MimeMultipart kann selbst ein anderer sein MimeMultipart. Das getTextFromMimeMultipart() Die folgende Methode wiederholt sich in solchen Fällen auf den Inhalt, bis der Nachrichtentext vollständig analysiert wurde.

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;
}

  • JFYI: In der JavaMail-FAQ von Orcale haben Sie behandelt multipart/alternative anders: oracle.com/technetwork/java/javamail/faq/index.html#mainbody. Ich bin mir nicht sicher, warum sie es tun, da ich es nicht kenne multipart.

    – Abhishek Gupta

    25. März 2017 um 13:28 Uhr

  • @AbhishekGupta Der Unterschied ist der für multipart/alternative, soll der Benutzeragent nur einen Teil auswählen, nicht verketten. Der FAQ-Code tut dies, während der obige Code dies nicht tut. Weitere Einzelheiten finden Sie in meiner Antwort unten.

    – Hendalst

    1. November 2018 um 7:53 Uhr

Benutzer-Avatar
hendalst

Diese Antwort erweitert Austins Antwort, um das ursprüngliche Problem mit der Behandlung von zu korrigieren multipart/alternative (// without break same text appears twice in my tests).

Der Text erscheint zweimal, weil für multipart/alternativewird erwartet, dass der Benutzeragent nur auswählt eines Teil.

Aus RFC2046:

Der Typ „multipart/alternative“ ist syntaktisch identisch mit „multipart/mixed“, aber die Semantik ist unterschiedlich. Insbesondere ist jeder Körperteil eine “alternative” Version derselben Information.

Systeme sollten erkennen, dass der Inhalt der verschiedenen Teile austauschbar ist. Systeme sollten den “besten” Typ basierend auf der lokalen Umgebung und Referenzen auswählen, in einigen Fällen sogar durch Benutzerinteraktion. Wie bei „mehrteilig/gemischt“ ist die Reihenfolge der Körperteile von Bedeutung. In diesem Fall erscheinen die Alternativen in einer Reihenfolge zunehmender Treue zum ursprünglichen Inhalt. Im Allgemeinen ist die beste Wahl der LETZTE Teil eines Typs, der von der lokalen Umgebung des Empfängersystems unterstützt wird.

Gleiches Beispiel mit Behandlung für Alternativen:

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;
}

Beachten Sie, dass dies ein sehr einfaches Beispiel ist. Es übersieht viele Fälle und sollte in seinem aktuellen Format nicht in der Produktion verwendet werden.

  • java.lang.ClassCastException: javax.mail.util.SharedByteArrayInputStream kann nicht in javax.mail.internet.MimeMultipart umgewandelt werden Ich erhalte diesen Fehler

    – Jerry

    30. Mai 2017 um 10:29 Uhr

  • Dies ist ein wirklich großartiges Beispiel – das beste derzeit im Internet, danke.

    – Zach Alberico

    18. Oktober 2017 um 21:14 Uhr

  • Für Google Mail gibt dies keinen E-Mail-Text zurück. Es wird immer ein Nullzeiger @ zurückgegeben. String html = (String) bodyPart.getContent(); Was könnte das Problem sein?

    – Pfarr

    18. Mai 2018 um 22:53 Uhr

  • Dieses Beispiel funktioniert genau so, wie ich es mir vorgestellt habe. Mail-.eml-Nachrichten können eine komplizierte Hierarchie haben und es sieht so aus, als ob diese Klasse alle Fälle enthalten kann. Außerdem muss ich sagen, diese Bibliothek javax.mail ist schnell und zuverlässig. Gute Wahl.

    – Hariprasad

    24. Mai 2019 um 12:26 Uhr


  • Ich verstehe nicht, warum sie nicht zur Verfügung gestellt haben .getParts() über die wir iterieren und dann bestimmen könnten, welche wir wollen. Wir könnten sogar einen Filter machen. Stattdessen müssen wir 0, 1, 2, 3 machen….

    – Romulusnr

    10. April 2020 um 4:26 Uhr

Erfinden Sie das Rad nicht neu! Sie können einfach Apache Commons Email verwenden (siehe hier)

Kotlin-Beispiel:

fun readHtmlContent(message: MimeMessage) = 
        MimeMessageParser(message).parse().htmlContent

Wenn eine E-Mail keinen HTML-Inhalt hat, aber einfachen Inhalt (Sie können dies überprüfen, indem Sie hatPlainContent und hasHtmlContent methoden), dann sollten Sie diesen Code verwenden:

fun readPlainContent(message: MimeMessage) = 
        MimeMessageParser(message).parse().plainContent

Java-Beispiel:

String readHtmlContent(MimeMessage message) throws Exception {
    return new MimeMessageParser(message).parse().getHtmlContent();
}

String readPlainContent(MimeMessage message) throws Exception {
    return new MimeMessageParser(message).parse().getPlainContent();
}

  • Das ist einfach genial! Der Java-Teil macht den Trick perfekt und es ist einfach und sauber

    – Sammy

    11. April 2019 um 15:36 Uhr

  • Geben Sie diesem Mann eine Auszeichnung! Ich habe drei Tage lang vergeblich versucht, das umzusetzen, was diese Bibliothek im Grunde tut. Danke, Mann! du bist lebensretter 🙂

    – Ahmet Eroğlu

    17. Juni 2020 um 10:42 Uhr

Benutzer-Avatar
Jurin

Unten ist eine Methode, die Text aus der Nachricht nimmt, falls BodyParts Text und HTML sind.

  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 "";
}

Aktualisieren. Es gibt einen Fall, in dem bodyPart selbst vom Typ multipart sein kann. (Ich habe eine solche E-Mail erhalten, nachdem ich diese Antwort geschrieben habe.) In diesem Fall müssen Sie die obige Methode mit Rekursion neu schreiben.

Ich glaube nicht, was wäre sonst, wenn a PartDer Mime-Typ von ist image/jpeg? Die API gibt eine zurück Object weil es intern versucht, Ihnen etwas Nützliches zu geben, vorausgesetzt, Sie wissen, was erwartet wird. Für Allzweck-Software soll es wie folgt verwendet werden:

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

Sie haben auch die rohe (eigentlich nicht so rohsiehe Javadoc) Part.getInputStream()aber ich denke, es ist unsicher anzunehmen, dass jede einzelne Nachricht, die Sie erhalten, textbasiert ist – es sei denn, Sie schreiben eine sehr spezifische Anwendung und haben die Kontrolle über die Eingabequelle.

  • javax.mail.Message implementiert die javax.mail.Part Schnittstelle

    – Raffaele

    29. Juni 2012 um 8:14 Uhr

Benutzer-Avatar
raggsss

Wenn Sie immer Text erhalten möchten, können Sie andere Typen wie “mehrteilig” usw. überspringen …

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

  • javax.mail.Message implementiert die javax.mail.Part Schnittstelle

    – Raffaele

    29. Juni 2012 um 8:14 Uhr

In meinem Fall wollte ich, dass der HTML-Code auch vorhanden ist, und ich habe auch nach einigen bereits erstellten Dienstprogrammen gesucht, also habe ich meinen mit dem folgenden Code repariert

import javax.mail.Message;
import org.apache.commons.io.IOUtils;
import javax.mail.internet.MimeUtility;
.....
String body = IOUtils.toString(
                 MimeUtility.decode(message.getInputStream(), "quoted-printable"),
                 "UTF-8"
              );

  • Segne deine Seele – habe einige der Antworten hier ausprobiert, diese funktioniert einfach.

    – Nykon

    25. April 2021 um 10:04 Uhr


1114190cookie-checkSo lesen Sie Text im E-Mail-Text mit javax.mail

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy