it-swarm.com.de

Wie man mit javax.mail Text im Mailkörper liest

ich entwickle eine Client-E-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 weiß, dass die Methode getContent() ein Objekt zurückgibt, weil der Inhalt ein String, ein MimeMultiPart, ein SharedByteArrayInputstream und anderes sein könnte (ich denke). .. Gibt es eine Möglichkeit, den Text immer innerhalb des Nachrichtenkörpers abzurufen? Vielen Dank!!

38
JackTurky

Diese Antwort erweitert Yurins Antwort . Das Problem, das er ansprach, war, dass der Inhalt eines MimeMultipart selbst ein anderer MimeMultipart sein kann. Die nachstehende getTextFromMimeMultipart() -Methode wird in solchen Fällen solange auf den Inhalt angewendet, 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;
}
58
Austin D

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

Der Text wird zweimal angezeigt, da das Benutzerprogramm für multipart/alternative Nur einen Teil auswählen soll.

Von RFC2046 :

Der Typ "Multipart/Alternative" ist syntaktisch identisch mit "Multipart/Mixed", aber die Semantik ist unterschiedlich. Insbesondere ist jedes der Körperteile 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 den Referenzen auswählen, in einigen Fällen sogar durch Benutzerinteraktion. Wie bei "multipart/mixed" ist die Reihenfolge der Körperteile von Bedeutung. In diesem Fall werden die Alternativen in einer Reihenfolge angezeigt, in der die Treue zum ursprünglichen Inhalt erhöht wird. Im Allgemeinen ist die beste Wahl der letzte Teil eines Typs, der von der lokalen Umgebung des Empfängersystems unterstützt wird.

Gleiches Beispiel bei der Behandlung von 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 fehlen viele Fälle und es sollte nicht in der Produktion im aktuellen Format verwendet werden.

19
hendalst

Nachfolgend finden Sie eine Methode, die Text aus der Nachricht entnimmt, falls bodyParts aus Text und HTML bestehen.

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

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

10
yurin

Ich glaube nicht, sonst würde was passieren, wenn der Mime-Typ eines Partimage/jpeg Ist? Die API gibt ein Object zurück, da sie intern versucht, Ihnen etwas Nützliches zu geben, vorausgesetzt, Sie wissen, was erwartet wird. Für Allzweck-Software ist folgende Verwendung vorgesehen:

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

Sie haben auch die rohen (eigentlich nicht so rohen , siehe Javadoc) Part.getInputStream() , aber ich Ich halte es für unsicher, anzunehmen, dass jede Nachricht, die Sie erhalten, textbasiert ist - es sei denn, Sie schreiben eine sehr spezielle Anwendung und haben die Kontrolle über die Eingabequelle.

9
Raffaele

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
    }
4
JAVAGeek

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

Beispiel Kotlin:

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

Wenn E-Mails keinen HTML-Inhalt haben, aber einfachen Inhalt (Sie können dies mit den Methoden hasPlainContent und hasHtmlContent überprüfen), 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();
}
1
grolegor