Comment lire le texte dans le corps du courrier en utilisant javax.courrier

je développe un client mail en utilisant javax.mail pour lire le courrier à l'intérieur de la boite mail:

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

je sais que la méthode getContent() renvoie un objet cause le contenu pourrait être un String , un MimeMultiPart , un SharedByteArrayInputstream et autre ( je pense )... Est-il un moyen d'obtenir toujours le texte à l'intérieur du corps de message? Merci!!

27
demandé sur JackTurky 2012-06-28 11:58:44

5 réponses

Cette réponse s'étend yurin la réponse de . La question qu'il était que le contenu d'un MimeMultipart peut lui-même être un autre MimeMultipart . La méthode getTextFromMimeMultipart() ci-dessous revient dans de tels cas sur le contenu jusqu'à ce que le corps du message ait été entièrement analysé.

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;
}
44
répondu Austin D 2017-06-12 09:51:17

Cette réponse s'étend Austin réponse pour corriger l'origine du problème avec le traitement de multipart/alternative ( // without break same text appears twice in my tests ).

le texte apparaît deux fois parce que pour multipart/alternative , l'agent utilisateur est censé choisir seulement un partie.

à Partir de RFC2046 :

le type" multipart/alternative " est syntaxiquement identique à "multipart / mixed", mais la sémantique est différente. En particulier, chacune des parties du corps est une autre version de la même information.

Systèmes devraient reconnaître que le contenu des différentes parties sont interchangeables. Les systèmes devraient choisir le" meilleur " type en fonction de l'environnement local et des références, dans certains cas même par l'intermédiaire de l'interaction avec les utilisateurs. Comme pour "multipartie / mixte", l'ordre des parties du corps est significatif. Dans ce cas, les solutions apparaissent dans un ordre croissant de fidélité au contenu d'origine. En général, le meilleur choix est la dernière partie d'un type pris en charge par l'environnement local du système bénéficiaire.

même exemple avec traitement pour les alternatives:

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

Notez que c'est un exemple très simple. Il manque de nombreux cas et ne devrait pas être utilisé dans la production dans son format actuel.

13
répondu pwrex 2017-05-23 12:26:33

ci-dessous est la méthode qui va prendre le texte du message dans le cas où bodyParts sont le texte et 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 "";
}

mise à Jour . Il y a un cas, que bodyPart lui-même peut être de type multipart. (J'ai rencontré un tel email après avoir écrit cette réponse. Dans ce cas, vous aurez besoin de réécrire méthode ci-dessus avec la récursivité.

10
répondu yurin 2016-01-08 17:36:49

Je ne pense pas, sinon que se passerait-il si le type mime d'un Part est image/jpeg ? L'API renvoie un Object parce qu'en interne elle essaie de vous donner quelque chose d'utile, à condition que vous sachiez ce qui est attendu. Pour les logiciels, il est destiné à être utilisé comme ceci:

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

vous avez aussi le brut (en fait pas tellement raw , voir le Javadoc) Part.getInputStream() , mais je pense que c'est il est dangereux de supposer que chaque message que vous recevez est basé sur un texte-à moins que vous rédigiez une application très spécifique et que vous ayez le contrôle sur la source d'entrée.

9
répondu Raffaele 2012-06-28 08:19:01

si vous voulez obtenir le texte toujours alors vous pouvez sauter d'autres types comme 'multipart' etc...

  Object body = message.getContent(); 
    if(body instanceof String){
    // hey it's a text
    }
4
répondu JAVAGeek 2015-04-24 05:51:30