如何使用javax.mail读取邮件正文中的文本

我正在使用javax.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); } 

我知道方法getContent()返回一个对象,因为内容可能是一个String ,一个MimeMultiPart ,一个SharedByteArrayInputstream和其他(我认为)…有没有办法在消息正文中获取文本? 谢谢!!

这个答案延伸了yurin的答案 。 他提出的问题是MimeMultipart的内容本身可能是另一个MimeMultipart 。 下面的getTextFromMimeMultipart()方法在这种情况下对内容进行递归,直到完全解析了消息体。

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

这个答案扩展了Austin的答案,以纠正处理multipart/alternative的原始问题( // without break same text appears twice in my tests )。

文本出现两次,因为对于multipart/alternative ,用户代理只能选择一个部分。

来自RFC2046 :

“multipart / alternative”类型在语法上与“multipart / mixed”相同,但语义不同。 特别地,每个身体部位是相同信息的“替代”版本。

系统应该认识到各个部分的内容是可以互换的。 系统应根据本地环境和参考选择“最佳”类型,在某些情况下甚至通过用户交互。 与“multipart / mixed”一样,身体部位的顺序也很重要。 在这种情况下,替代方案以对原始内容的忠诚度增加的顺序出现。 通常,最佳选择是接收方系统本地环境支持的类型的最后部分。

与替代品处理相同的例子:

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

请注意,这是一个非常简单的示例。 它错过了很多案例,不应该以当前格式用于生产。

下面是在bodyParts是text和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 ""; } 

更新 。 有一种情况,bodyPart本身可以是multipart类型。 (在写完这个答案之后我遇到了这样的电子邮件。)在这种情况下,你需要用递归重写上面的方法。

我不这么认为,否则如果Part的mime类型是image/jpeg会发生什么? API返回一个Object因为在内部它会尝试为您提供有用的东西,前提是您知道预期的内容。 对于通用软件,它的用途如下:

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

你也有原始的(实际上不那么原始 ,请参阅Javadoc) Part.getInputStream() ,但我认为假设你收到的每条消息都是基于文本的消息是不安全的 – 除非你正在编写一个非常具体的应用程序并且您可以控制输入源。

如果你想总是得到文本,那么你可以跳过其他类型,如’multipart’等…

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