How to handle multipart/alternative mail with JavaMail?
I found reading e-mail with the JavaMail library much more difficult than expected. I don't blame the JavaMail API, rather I blame my poor understanding of RFC-5322 -- the official definition of Internet e-mail.
As a thought experiment: Consider how complicated an e-mail message can become in the real world. It is possible to "infinitely" embed messages within messages. Each message itself may have multiple attachments (binary or human-readable text). Now imagine how complicated this structure becomes in the JavaMail API after parsing.
A few tips that may help when traversing e-mail with JavaMail:
Message
andBodyPart
both implementPart
.MimeMessage
andMimeBodyPart
both implementMimePart
.- Where possible, treat everything as a
Part
orMimePart
. This will allow generic traversal methods to be built more easily.
These Part
methods will help to traverse:
String getContentType()
: Starts with the MIME type. You may be tempted to treat this as a MIME type (with some hacking/cutting/matching), but don't. Better to only use this method inside the debugger for inspection.- Oddly, MIME type cannot be extracted directly. Instead use
boolean isMimeType(String)
to match. Read docs carefully to learn about powerful wildcards, such as"multipart/*"
.
- Oddly, MIME type cannot be extracted directly. Instead use
Object getContent()
: Might beinstanceof
:Multipart
-- container for morePart
s- Cast to
Multipart
, then iterate as zero-based index withint getCount()
andBodyPart getBodyPart(int)
- Note:
BodyPart
implementsPart
- Note:
- In my experience, Microsoft Exchange servers regularly provide two copies of the body text: plain text and HTML.
- To match plain text, try:
Part.isMimeType("text/plain")
- To match HTML, try:
Part.isMimeType("text/html")
- To match plain text, try:
- Cast to
Message
(implementsPart
) -- embedded or attached e-mailString
(just the body text -- plain text or HTML)- See note above about Microsoft Exchange servers.
InputStream
(probably a BASE64-encoded attachment)
String getDisposition()
: Value may benull
- if
Part.ATTACHMENT.equalsIgnoreCase(getDisposition())
, then callgetInputStream()
to get raw bytes of the attachment.
- if
Finally, I found the official Javadocs exclude everything in the com.sun.mail
package (and possibly more). If you need these, read the code directly, or generate the unfiltered Javadocs by downloading the source and running mvn javadoc:javadoc
in the mail
project module of the project.
Did you find these JavaMail FAQ entries?
- How do I read a message with an attachment and save the attachment?
- How do I tell if a message has attachments?
- How do I find the main message body in a message that has attachments?