JavaMail API: Message in EML format

Our application was already using JavaMail (javax.mail.*) as a way to inform our users. But for logging purposes we wanted to store all the emails we send in our database (and make them downloadable using our GUI).

It turns out this is pretty easy to do!

Let’s start with some very basic email code we already had in place:

// Some method to construct a MimeMessage:Messagemessage=createMailMessage(input);Transport.send(message);

What we need to do now is to ‘render’ the entire email in a binary format, including all the possible attachements, multipart things, from and to headers etc.

It turns out there is a convinient method for doing just that: message.writeTo(OutputStream)

Messagemessage=createMailMessage(input);// some method to construct a MimeMessage// Retrieve the entire message as byte[]:ByteArrayOutputStreamout=newByteArrayOutputStream();message.writeTo(out);byte[]contents=out.toByteArray();// Next we store the byte[] in our database (JPA) entity:ArchivedMailarchivedMail=newArchivedMail(sender,contents,LocalDateTime.now());mailArchive.store(archivedMail);Transport.send(message);

Our own little POJO entity (ArchivedMail) is stored in the database with some additional information that allows us to search the messages. The final step is to make a download link and present the email in a readable format to the users.

We’re using Wicket and thus the following example is Wicket code, but you could just as easily create a Servlet to return the data:

// Add the Wicket link-component to our page:add(newLink<ArchivedMail>("wicketLinkId",Model.of(somemail)){@OverridepublicvoidonClick(){IResourceStreamresourceStream=newAbstractResourceStreamWriter(){@Overridepublicvoidwrite(OutputStreamoutput)throwsIOException{// When clicked output a stream which contains the raw byte[]:output.write(getModelObject().getBytes());}@OverridepublicStringgetContentType(){// Add the content type for an EML file:return"message/rfc822";}};// Schedule the handler to return our resource stream (with a fancy name):getRequestCycle().scheduleRequestHandlerAfterCurrent(newResourceStreamRequestHandler(resourceStream).setFileName("mail.eml"));}});

Conclusion

Using JavaMail (javax.mail) it is very easy to get the ‘raw’ contents of an email when sending it.

This can be stored and downloaded in EML-format. It contains everything you need, mime, multipart, attachements and all the from/to headers.