Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read text inside body of mail using javax.mail

i'm developing a client mail using javax.mail to read mail inside mail box:

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

I know that the method getContent() returns an object cause the content could be a String, a MimeMultiPart, a SharedByteArrayInputstream and other ( i think )... Is there a way to get always the text inside body of message? Thanks!!

like image 532
Jayyrus Avatar asked Jun 28 '12 07:06

Jayyrus


2 Answers

This answer extends yurin's answer. The issue he brought up was that the content of a MimeMultipart may itself be another MimeMultipart. The getTextFromMimeMultipart() method below recurses in such cases on the content until the message body has been fully parsed.

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; } 
like image 66
Austin Avatar answered Oct 26 '22 11:10

Austin


This answer extends Austin's answer to correct the orginal issue with treatment of multipart/alternative (// without break same text appears twice in my tests).

The text appears twice because for multipart/alternative, the user agent is expected to choose only one part.

From RFC2046:

The "multipart/alternative" type is syntactically identical to "multipart/mixed", but the semantics are different. In particular, each of the body parts is an "alternative" version of the same information.

Systems should recognize that the content of the various parts are interchangeable. Systems should choose the "best" type based on the local environment and references, in some cases even through user interaction. As with "multipart/mixed", the order of body parts is significant. In this case, the alternatives appear in an order of increasing faithfulness to the original content. In general, the best choice is the LAST part of a type supported by the recipient system's local environment.

Same example with treatment for 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; } 

Note that this is a very simple example. It misses many cases and should not be used in production in it's current format.

like image 22
hendalst Avatar answered Oct 26 '22 10:10

hendalst