java-mail: tree-like mail structure traversal
Just as of recently, I have been playing around with Java Mail, a library I overally enjoy working with, except for one thing perhaps: Somehow I miss a consistent data structure backing it to allow for traversing an e-mail structure in a clean way…
Maybe I just haven’t yet found a better starting point, but somehow then and now I am still unsure why to have javax.mail.Multipart as an abstract class extending Object, representing multipart messages (i.o.w. virtually everything to include either attachments, forwarded messages, inline images or “alternate” parts, like the same content in plain text and in HTML), and, on the other side, the javax.mail.Part interface to deal with parts included in messages. Somehow the latter seems sane, and, given javax.mail.Multipart would actually implement javax.mail.Part, some things possibly would be a little easier… or wouldn’t, if I just did them right, however. 😉
Anyway, to programmatically deal with mails in our internal environment (where mail processing happens to be done automatically from within a Java EE application traversing an IMAP folder tree, looking at new messages and extracting things as it sees fit), I made up a tree structure to wrap these things up and provide a (hopefully) straighforward yet concise way of accessing mail-parts and content despite its actual content type, MIME structure and related things. Sample code can be found here, explanations on that:
- The project uses maven2 and the Swing Application Framework for the UI stuff. Along with the maven2 project structure this project can be simply opened and launched from within NetBeans IDE with installed maven2 toolings. Running “natively” (without an IDE), make sure to invoke
mvn assembly:assembly
to build the project and then run the app usingjava -jar target/toys-text-mailarchiver-0.0.8-SNAPSHOT-jar-with-dependencies.jar
to actually get things goin’. - Before building and eventually running things, open the
net.z428.toys.mailtext.VisualMailView
class and set the mail server host name and credentials (your.server.name
,your.server.userid
,your.server.password
) to sane values. While in there, also make sure to set a valid IMAP starting folder or, better, uncomment the//this.mailViewMain.setFolderList(this.connector.getStore().getDefaultFolder().list());
line to use the standard folder prefix. - Likewise, you should have a look at
pom.xml
, download and possibly install the Swing Application Framework .jar to your local .m2 repository – don’t worry as if you don’t, maven2 will tell you (how) to do so.
Running the application (and given you set up your IMAP access right), you will want to see a screen something like the following (after you chose a folder and clicked the “List” button, that is). What to see:
At first, each message is a child of the tree root. If possible, the messages are labeled using either the “Subject” string as found in the mail or some other meaningful value (attachment, filename, content type or the like). Names starting with ">"
indicate a “top-level” mail container which is not of that much interest in the UI as it might be in a non-UI application using the same structure. Expanding the messages in the tree allows for browsing their MIME structure, exploring what kind of data they do contain:
Talking implementation, there basically are two classes of interest here:
net.z428.toys.mailtext.PartContainer
is ought to be an abstraction ofjavax.mail.Part
,javax.mail.Multipart
and the data objects they could contain. The idea ofPartContainer
mainly is to provide a straightforward way of accessing part headers as well as the part content (accessible at best using thegetPayloadAsStream()
method returning anInputStream
to read the mail content in this part from.PartContainer
objects are supposed to have otherPartContainer
s (representing embedded parts they might contain) as children, as well as having thePartContainer
that encloses them added as parent (in other words, a tree structure). In “stock” Java Mail, you are likely to use thegetContent()
method for that and figure out which kind of class to get in return. In thePartContainer
structure, a difference is being made between “actual” data and embedded parts, which might or might not make sense depending upon what you want / need.- Along with it there is a
net.z428.toys.mailtext.PartDumper
class which provides a facility for buildingPartContainer
trees fromjavax.mail.Message
objects. net.z428.toys.mailtext.ui.TreeHelper
, finally, provides a helper function for building aDefaultMutableTreeNode
based tree for display inJTree
.
This contains some of the logic to differ between javax.mail.Part
, javax.mail.Multipart
and actual data in an e-mail representation.
Concluding, I have to state that at least the UI is rather flaky and not very fault tolerant, and most of the code has yet to see heavy load test (which will happen the next days as it is to replace an older, way more limited implementation of mail parsing not honouring the tree-like structure of nested parts which brings some serious issues at times). However as I’ve been searching quite a while for something like that in relation to Java-Mail, I’m still posting it here, maybe it will ease someones search and / or prove usable to one or another – mainly this is not a “finished”, ready-to-use implementation of anything but rather thought of as an inspiration for you to have a look at and get started in case you also might be searching… Comments / hints / suggestions, of course, always appreciated.
Code: toys-mailarchiver.tgz (to be used according to the terms of CDDL)