Comment gérer multipart/alternative mail avec JavaMail?

j'ai écrit une application qui reçoit tous les e-mails d'une boîte de réception, filtre les e-mails qui contiennent une chaîne spécifique et puis met ces e-mails dans une liste de tableaux.

après que les e-mails sont mis dans la liste, je fais quelques trucs avec le sujet et le contenu de ces e-mails. Cela fonctionne très bien pour les e-mails sans pièce jointe. Mais quand j'ai commencé à utiliser des e-mails avec des pièces jointes, tout ne fonctionnait plus comme prévu.

C'est mon code:

public void getInhoud(Message msg) throws IOException {
    try {
        cont = msg.getContent();
    } catch (MessagingException ex) {
        Logger.getLogger(ReadMailNew.class.getName()).log(Level.SEVERE, null, ex);
    }
    if (cont instanceof String) {
        String body = (String) cont;


    } else if (cont instanceof Multipart) {
        try {
            Multipart mp = (Multipart) msg.getContent();
            int mp_count = mp.getCount();
            for (int b = 0; b < 1; b++) {
                    dumpPart(mp.getBodyPart(b));
            }
        } catch (Exception ex) {
            System.out.println("Exception arise at get Content");
            ex.printStackTrace();
        }
    }
}

public void dumpPart(Part p) throws Exception {
    email = null;
    String contentType = p.getContentType();
    System.out.println("dumpPart" + contentType);
    InputStream is = p.getInputStream();
    if (!(is instanceof BufferedInputStream)) {
        is = new BufferedInputStream(is);
    }
    int c;
    final StringWriter sw = new StringWriter();
    while ((c = is.read()) != -1) {
        sw.write(c);
    }

    if (!sw.toString().contains("<div>")) {
        mpMessage = sw.toString();
        getReferentie(mpMessage);
    }
}

Le contenu de l'e-mail est stocké dans une Chaîne.

ce code fonctionne très bien quand j'essaie de lire des mails sans pièce jointe. Mais si j'utilise un e-mail avec pièce jointe la chaîne contient aussi du code HTML et même le codage de pièce jointe. Finalement je veux stocker la pièce jointe et le contenu d'un e-mail, mais ma première priorité est d'obtenir juste le texte sans aucun HTML ou le codage de pièce jointe.

Maintenant, j'ai essayé une approche différente pour gérer le les différentes parties:

public void getInhoud(Message msg) throws IOException {
    try {
        Object contt = msg.getContent();

        if (contt instanceof Multipart) {
            System.out.println("Met attachment");
            handleMultipart((Multipart) contt);
        } else {
            handlePart(msg);
            System.out.println("Zonder attachment");

        }
    } catch (MessagingException ex) {
        ex.printStackTrace();
    }
}

public static void handleMultipart(Multipart multipart)
        throws MessagingException, IOException {
    for (int i = 0, n = multipart.getCount(); i < n; i++) {
        handlePart(multipart.getBodyPart(i));
        System.out.println("Count "+n);
    }
}

 public static void handlePart(Part part)
        throws MessagingException, IOException {

    String disposition = part.getDisposition();
    String contentType = part.getContentType();
    if (disposition == null) { // When just body
        System.out.println("Null: " + contentType);
        // Check if plain
        if ((contentType.length() >= 10)
                && (contentType.toLowerCase().substring(
                0, 10).equals("text/plain"))) {
            part.writeTo(System.out);
        } else if ((contentType.length() >= 9)
                && (contentType.toLowerCase().substring(
                0, 9).equals("text/html"))) {
            part.writeTo(System.out);
        } else if ((contentType.length() >= 9)
                && (contentType.toLowerCase().substring(
                0, 9).equals("text/html"))) {
            System.out.println("Ook html gevonden");
            part.writeTo(System.out);
        }else{
            System.out.println("Other body: " + contentType);
            part.writeTo(System.out);
        }
    } else if (disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
        System.out.println("Attachment: " + part.getFileName()
                + " : " + contentType);
    } else if (disposition.equalsIgnoreCase(Part.INLINE)) {
        System.out.println("Inline: "
                + part.getFileName()
                + " : " + contentType);
    } else {
        System.out.println("Other: " + disposition);
    }
}

C'est ce qui est retourné de System.out.printlns

Null: multipart/alternative; boundary=047d7b6220720b499504ce3786d7
Other body: multipart/alternative; boundary=047d7b6220720b499504ce3786d7
Content-Type: multipart/alternative; boundary="047d7b6220720b499504ce3786d7"

--047d7b6220720b499504ce3786d7
Content-Type: text/plain; charset="ISO-8859-1"

'Text of the message here in normal text'

--047d7b6220720b499504ce3786d7
Content-Type: text/html; charset="ISO-8859-1"
Content-Transfer-Encoding: quoted-printable

'HTML code of the message'

cette approche renvoie le texte normal de l'e-mail mais aussi le codage HTML du courrier. Je ne comprends vraiment pas pourquoi cela se produit, je l'ai googlé mais il semble qu'il n'y a personne d'autre avec ce problème.

Toute aide est appréciée,

Merci!

10
demandé sur Jef 2012-11-11 18:24:00

3 réponses

j'ai trouvé la lecture des e-mails avec la bibliothèque JavaMail beaucoup plus difficile que prévu. Je ne blâme pas L'API JavaMail, mais plutôt ma mauvaise compréhension de RFC-822 -- la définition officielle de l'e-mail sur Internet.

comme une expérience de pensée: Considérez comment un message électronique peut devenir compliqué dans le monde réel. Il est possible d'intégrer "infiniment" des messages dans des messages. Chaque message lui-même peut avoir plusieurs pièces jointes (binaires ou lisibles par l'utilisateur) texte.) Maintenant, imaginez à quel point cette structure devient compliquée dans L'API JavaMail après l'analyse.

quelques conseils qui peuvent aider lors de la traversée d'e-mail avec JavaMail:

Message,Multipart et BodyPart œuvre Part. Dans la mesure du possible, traitez tout comme un Part. Cela permettra de construire plus facilement des méthodes générales de traversée.

ceux-ci Part les méthodes aideront à traverser:

  • String getContentType(): commence avec le type MIME. Vous pourriez être tenté de traiter cela comme un type de MIME (avec certains hacking/coupe/matching), mais ne le faites pas. Il est préférable d'utiliser cette méthode uniquement à l'intérieur du débogueur pour l'inspection.
    • curieusement, le type MIME ne peut pas être extrait directement. Au lieu d'utiliser boolean isMimeType(String) pour correspondre. Lisez attentivement docs pour en savoir plus sur les caractères génériques puissants, tels que "multipart/*".
  • Object getContent(): Peut être instanceof:
    • Multipart -- conteneur pour plus d' Parts
      • Distribution de Multipart, puis itérer comme index à base zéro avec int getCount() et BodyPart getBodyPart(int)
        • Remarque:
      • d'après mon expérience, les serveurs Microsoft Exchange fournissent régulièrement deux copies du corps du texte: Texte en clair et HTML.
        • match en texte brut, à essayer: Part.isMimeType("text/plain")
        • Pour correspondre HTML, essayez: Part.isMimeType("text/html")
    • Message (implémente Part) -- incorporé ou attaché e-mail
    • String (juste le corps du texte -- texte brut ou HTML)
      • voir la note ci-dessus à propos des serveurs Microsoft Exchange.
    • InputStream (probablement encodée en BASE64 pièce jointe)
  • String getDisposition(): la Valeur peut être nulle
    • si Part.ATTACHMENT.equalsIgnoreCase(getDisposition()), puis d'appeler getInputStream() pour obtenir les octets bruts de la pièce jointe.

enfin, j'ai trouvé le Javadocs officiels exclure tout dans l' com.sun.mail package (et peut-être plus). Si vous en avez besoin, lisez le code directement, ou générez les Javadocs non filtrés par télécharger les sources et en cours d'exécution mvn javadoc:javadoc dans le mail module projet du projet.

20
répondu kevinarpe 2018-01-19 15:09:26

pour donner suite aux conseils utiles de Kevin, l'analyse des types D'objets Java contenus dans votre courriel par rapport à leurs noms canoniques (ou noms simples) peut également être utile. Par exemple, en regardant une boîte de réception que j'ai en ce moment, sur 486 messages 399 sont des chaînes, et 87 sont des MimeMultipart. Ceci suggère que - pour mon email typique - une stratégie qui utilise instanceof d'abord détacher les cordes est préférable.

des chaînes, 394 sont text / plain, et 5 sont texte/html. Ce ne sera pas le cas pour la plupart; il est le reflet de mon courriel alimente dans cette boîte de réception en particulier.

Mais attendez - plus!!! :-) Le HTML se faufile dans la il cependant: 87 Multipart, 70 sont multipart/alternative. Aucune garantie, mais la plupart (si ce n'est toutes) sont des textes + HTML.

sur les 17 autres multiparties, soit dit en passant, 15 sont multiparties / mélangées, et 2 sont multiparties/signées.

mon cas d'utilisation avec cette boîte de réception (et une autre) est principalement pour regrouper et analyser le contenu connu des listes de diffusion. Je ne peux ignorer aucun des messages, mais une analyse de ce genre m'aide à rendre mon traitement plus efficace.

1
répondu Arved Sandstrom 2014-05-17 15:29:02