Luckily, we at engfer(s) had a task to attach a system message to the bottom of every email (html & text) that leaves the system. We thought it would be easy; however, it was not. It took hours of println()’s to figure out how to just get to the message body. We will share some information we gathered with you so it may help alleviate the pain that we had to go through.
The Example Problem
- Task: Append the String “<div style=’font-size: 8pt; font-family: sans-serif; clear: both;’ align=’center’><i>:: Sent From the System ::</i></div>” to every email that leaves the system
- Background: There exists a place where all emails in the system get filtered through a certain location. It will be our job to intercept these messages, attach the string, and send them on their merry way
The Quirky Structure of the Java Mail Message
If you get bored and decide to parse through the javdocs for the javax.mail.Message, you will see plenty of getter’s and setter’s. These are great if you want to view or change the Date, Subject, From, Folder, Recipients and other useless information for our example. Hmm, but nothing in there about getting the text or body directly.
Well, there is a getContent() method from the extended class Part that returns an Object, so maybe that is probably where the body lies (and it does). Unfortunately, an Object is returned, so we are going to have to use the ugly instanceof operator to test what the heck it is. At this point, all we know is shown by Figure 1; we have a Message with some Object called ‘content’.

Consequently, we played around with some println()’s and the instanceof operator to figure out what the heck the Object is. Well, we came across a few situations of what that Object might be/contain.
First, let’s see what code scaffold we came up with to test this (we are just trying to grab the message content):
// There exists some parameter pMessage
// which is a javax.mail.Message
try {
// Try and grab the unknown content
Object content = pMessage.getContent();
}catch ( MessagingException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
1) The Content is an Instance of a String
As you can see in Figure 2, we found that the content was nothing more than a simple String that contained the body of the message.

Wow, that was easy! We can just take the body, add our html-stripped version of our String, set the new content (which sets the MIME type to “text/plain”), and call it a day (lines 08 – 14):
// There exists some parameter pMessage
// which is a javax.mail.Message
try {
// Try and grab the unknown content
Object content = pMessage.getContent();
// Grab the body content text
if ( content instanceof String ) {
String body = (String) content;
// Add our custom message
body += stripTags( mesgStr );
// Set the new content
pMessage.setContent( body );
}
}catch ( MessagingException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
Doh! The only problem is that having the message content as String is a super trivial case.
2) The Content is an Instance of a Multipart that Contains Text and HTML Versions of the Message
Much of today’s email is sent in HTML; however, some people/clients still don’t want to see (or can’t see) HTML email, so a text version of the email is usually included as well.

Figure 3 shows exactly how a text and HTML version of an email is packaged.
The Content is an instanceof Multipart which contains a series of BodyPart’s; heck, it can even be an instance of a MimeMultipart with MimeBodyPart’s (which it happens to be in our case).
Since MimeBodyPart (and BodyPart) extends Part as well, they too have the getContent() method; however, it is at this point that we should call the isMimeType( String mimeType ) method to see if it’s “text/plain” or “text/html”.
Let’s put our findings into code. The one thing we’ll be sure to do is make parsing of a Multipart a method of it’s own (line 27 below); we shall see why in a few moments.
public void editMessage( Message pMessage ) {
// There exists some parameter pMessage
// which is a javax.mail.Message
try {
// Try and grab the unknown content
Object content = pMessage.getContent();
// Grab the body content text
if ( content instanceof String ) {
String body = (String) content;
// Add our custom message
body += stripTags( mesgStr );
// Set the new content
pMessage.setContent( body );
} else if ( content instanceof Multipart ) {
// Make sure to cast to it's Multipart derivative
parseMultipart( (Multipart) content );
}
}catch ( MessagingException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
}
// Parse the Multipart to find the body
public void parseMultipart( Multipart mPart ) {
// Loop through all of the BodyPart's
for ( int i = 0; i < mPart.getCount(); i++ ) {
// Grab the body part
BodyPart bp = mPart.getBodyPart( i );
// Grab the disposition for attachments
String disposition = mPart.getDisposition();
// It's not an attachment
if ( disposition == null && bp instanceof MimeBodyPart ){
MimeBodyPart mbp = (MimeBodyPart) bp;
// Time to grab and edit the body
if ( mbp.isMimeType( "text/plain" ) {
// Grab the body containing the text version
String body = (String) mbp.getContent();
// Add our custom message
body += stripTags( mesgStr );
// Reset the content
mbp.setContent( body, "text/plain" );
} else if ( mbp.isMimeType( "text/html" ) {
// Grab the body containing the HTML version
String body = (String) mbp.getContent();
// Add our custom message to the HTML before
// the closing </body>
body = addStrToHtmlBody( mesgStr, body );
// Reset the content
mbp.setContent( body, "text/html" );
}
}
}
}
Notice how on lines 40 & 48 how we made sure to check the MimeType’s; also notice how we checked for a disposition on lines 33 & 36 to see if it is an attachment. We aren’t going to show you the addStrToHtmlBody( mesgStr, body ) implementation because we think you can do it easily enough with some regular expressions or body.replace()’s.
The code at this point is almost finished; there is just one more major instance that will break our code.
3) The Content is an Instance of a Multipart that Contains Attachments and a “Sub”-Multipart that Contains the Text and HTML Versions of the Message
For some unworldly reason, Mr. eMail man decided that instead of adding attachments as BodyPart’s to the current Multipart, he decided to bury the message text Multipart as a sub-element to another Multipart.
What?! Yes, you read that right. It’s a Multipart containing two or more BodyParts: 1) A BodyPart(s) that contain(s) the attchment(s) 2) A BodyPart whose content is a Multipart which has the two MimeBodyPart’s containing the text & HTML versions of the message.
What in the heck did that mean? Just stare at Figure 4 for a bit and read the last paragraph again.

It’s the most screwy thing we can think of right now. We’re sure there’s a valid reason for it; if you know what it is, feel free to post a comment about it.
Now, let’s go back and fix our code to handle this haphazard situation.
public void editMessage( Message pMessage ) {
// There exists some parameter pMessage
// which is a javax.mail.Message
try {
// Try and grab the unknown content
Object content = pMessage.getContent();
// Grab the body content text
if ( content instanceof String ) {
String body = (String) content;
// Add our custom message
body += stripTags( mesgStr );
// Set the new content
pMessage.setContent( body );
} else if ( content instanceof Multipart ) {
// Make sure to cast to it's Multipart derivative
parseMultipart( (Multipart) content );
}
}catch ( MessagingException e ) {
e.printStackTrace();
} catch ( IOException e ) {
e.printStackTrace();
}
}
// Parse the Multipart to find the body
public void parseMultipart( Multipart mPart ) {
// Loop through all of the BodyPart's
for ( int i = 0; i < mPart.getCount(); i++ ) {
// Grab the body part
BodyPart bp = mPart.getBodyPart( i );
// Grab the disposition for attachments
String disposition = mPart.getDisposition();
// It's not an attachment
if ( disposition == null && bp instanceof MimeBodyPart ){
MimeBodyPart mbp = (MimeBodyPart) bp;
// Check to see if we're in the screwy situation where
// the message text is buried in another Multipart
if ( mbp.getContent() instanceOf Multipart ) {
// Use recursion to parse the sub-Multipart
parseMultipart( (Multipart) mbp.getContent() );
} else {
// Time to grab and edit the body
if ( mbp.isMimeType( "text/plain" ) {
// Grab the body containing the text version
String body = (String) mbp.getContent();
// Add our custom message
body += stripTags( mesgStr );
// Reset the content
mbp.setContent( body, "text/plain" );
} else if ( mbp.isMimeType( "text/html" ) {
// Grab the body containing the HTML version
String body = (String) mbp.getContent();
// Add our custom message to the HTML before
// the closing </body>
body = addStrToHtmlBody( mesgStr, body );
// Reset the content
mbp.setContent( body, "text/html" );
}
}
}
}
}
Check out lines 41 – 44. Ahhh! Now we see why we made parseMultipart a separate function, so we could use recursion to tackle the problem for us!
Great work!
I was working on the same issue and couldn’t find anything on it until I got to this page which shows it perfectly.
I am working on this problem too.
I write my own code with the same idea. but it does not work – setContent do nothing!
I decide that make some mistake and try to use your code, but it does not compile: there is not method setContent wich take one parametr of type String
String body = (String) content;
// Add our custom message
body = data;
// Set the new content
–>> msg.setContent( body );
If you look at the two setContent methods on javax.mail.Message (which comes from the implemented interface javax.mail.Part), you will see that the one of the methods takes a single parameter, javax.mail.Multipart, and the other method takes an Object and and a String.
The correct method you want to use is the two parameter version; the second parameter is the MIME type (“text/html”, “text/plain”, etc). My code may well be incorrect now that I think about it, it was adapted from something I have made, so I didn’t test if it compiled.
Hello!
Code in post contain right idea but has some errors. Main error is that changes not saved.
This code works properly (it edits only “text/plain”, but for “text/html” changes are minimal):
public void updateTextInMessage (Message msg) throws MessagingException, IOException { Object content = msg.getContent (); if (content instanceof String) updateTextInMessage ((Part) msg); else { updateTextInMessage ((Multipart) content); msg.setContent ((Multipart) content); } msg.saveChanges (); } private void updateTextInMessage (Multipart multipart) throws MessagingException, IOException { int partsCount = multipart.getCount (); for (int i = 0; i < partsCount; i) { BodyPart bodyPart = multipart.getBodyPart (i); String disposition = bodyPart.getDisposition (); if (disposition == null && bodyPart instanceof MimeBodyPart) { MimeBodyPart mimeBodyPart = (MimeBodyPart) bodyPart; Object content = mimeBodyPart.getContent (); if (content instanceof Multipart) { updateTextInMessage ((Multipart) content); mimeBodyPart.setContent ((Multipart) content); } else if (mimeBodyPart.isMimeType ("text/plain")) updateTextInMessage ((Part) bodyPart); } } } private void updateTextInMessage (Part textPart) throws MessagingException, IOException { String body = (String) textPart.getContent (); body = "\r\n\r\nAdded text.\r\n"; textPart.setContent (body, "text/plain"); }