Update – if you’re using Tomcat and want to use JNDI then follow this post instead
Sending email via Mandrill from a Java web server
We’ve decided to do a bit of experimentation of using Mandrill to send all our transactional emails from our Java web server. We already use Mailchimp for our mailing list and it offers an integration with Mandrill. I found it a little harder than I’d expected to use Javamail with SMTP authentication and so I thought I’d post a quick how to.
Connecting using an Authenticator
After running up against a bug in JavaMail when saving a PasswordAuthentication
(see below) my preferred approach is now to use an javax.mail.Authenticator
to connect. You must ensure you set the session property mail.smtp.auth=true
first.
mailProperties.setProperty("mail.transport.protocol", "smtp"); mailProperties.setProperty("mail.smtp.host", host); mailProperties.setProperty("mail.smtp.port", String.valueOf(port)); mailProperties.setProperty("mail.smtp.user", username); mailProperties.setProperty("mail.smtp.auth", "true"); final Session session = Session.getInstance(mailProperties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); final MimeMessage msg = new MimeMessage(session); // set required message properties Transport.send(msg);
Bug in JavaMail service for non standard SMTP ports?
The main reason I ran into difficultly was because Mandrill uses a non-standard SMTP port and I think there’s a bug in javax.mail.Service
that is exposed in these circumstances. One way to authenticate is to register a javax.mail.PasswordAuthentication
for your connection’s javax.mail.URLName
with your javax.mail.Session
before calling javax.mail.Transport.send(msg)
. However if you use Transport.send()
then the instance of URLName
created to retrieve the PasswordAuthentication
object will always use the standard port. The version of JavaMail I discovered this in (by running a debuger) was 1.4.5.
Don’t specify a port in your URLName
when registering your PasswordAuthentication
The solution is specify the default port in the URLName
you build to register the PasswordAuthentication
object, even if you’re actually connecting via a non-standard port.
mailProperties.setProperty("mail.transport.protocol", "smtp"); mailProperties.setProperty("mail.smtp.host", host); mailProperties.setProperty("mail.smtp.port", String.valueOf(port)); mailProperties.setProperty("mail.smtp.user", username); final Session session = Session.getInstance(mailProperties, null); session.setPasswordAuthentication( new URLName("smtp", host, -1, null, username, null), new PasswordAuthentication(username, password); final MimeMessage msg = new MimeMessage(session); // set required message properties Transport.send(msg);