How to interact with Apache James in integration tests
At times, I have the
need for my development testing to interact with an email server (e.g. testing
cgi-bin
scripts,
JIRA mail plug-ins), to verify that
emails are sent and received by either my components or external systems.
I found that Apache James was quick to get up and
running, with very little configuration.
Apache James is a open source Java implementation of a fully-featured mail
server. It is component based, so you can attach or detach what ever parts you
like (e.g. I am only interested in the SMTP and IMAP connectors), and for my
purposes requires very little setup (although I wouldn't recommend using
default settings in a permanent production environment).
Note that to use the default ports (SMTP: 25, IMAP: 143), you'll have to run
as root on unix, or administrator on Windows.
James can automatically create a user account for the recipients(s) when
receiving an email, if they don't already exist. So we are free to send emails
to and check the accounts of which ever user we want, without a setup
overhead!
Mail Client Utility
When the James server is running, a utility class will
help us to send emails and clear user's inboxes (this class based on Claude
Duguay's IBM
article).
The parent class javax.mail.Authenticator helps us with the
javax.mail.Session connection.
This utility class gives us the ability to send and receive messages, as well
as providing a method of pausing in a mailbox until a new message arrives.
You'll notice the constructor includes a username and password, although the
default behaviour of James when it receives an email for an account that
doesn't exist is to create a new account with a password that is the same as
the username. The host parameter will most likely be localhost unless you've
deployed James to another server.
The waitForIncomingEmail method allows us to pause execution while waiting
for an email to be received, useful if the next test stage requires an email
to be present in the inbox.
We can also clear out an inbox using checkInbox with the constant
CLEAR_MESSAGES.
Test class setup
In a JUnit test class, we can set up references to user
accounts using instances of JamesMailClient and clear out the inboxes when
we've finished.
If the account doesn't exists (i.e. before you've sent an email to the account
or created it manually), a NoSuchProviderException would be thrown when the
account is accessed in tearDown().
Our test harness is then ready for test cases to send and receive emails!
Test Case Usage
Using the functions in JamesMailClient, this code shows
foo@localhost sending an email to bar@localhost, and bar waiting to
receive it!
Apache James & Maven
So far I've been simply running Apache James from
the command line, but it does exist in the maven repository
(http://repo1.maven.org/maven2/org/apache/james/).
In the future I could be tempted to write a maven plugin or similar for it to
launch for integration testing targets.. Stay tuned!