Sunday, May 15, 2016

Secure SMTP with Spring JavaMailSender


Overview

Like many cost-effective individuals out there I migrated most of my email service which I was paying approximately $50/year for to use Google Apps For Your Domain. This is a free service that in fact I am very satisfied with. But using the smtp service with the Spring JavaMailSender on my old email account was straight forward. The problem I now have is that Google Apps For Your Domain uses the smtps protocol to send emails and because I was using an older version of Java Mail (1.3) I could not programmatically send emails using the secure smtp protocol. In addition to that, the default implemation of JavaMailSender (JavaMailSenderImpl.java) in Spring Framework currently does not have the ability to smoothly handle sending messages using the secure smtp (smtps) protocol.

I stumbled into this when developing a web application that requires an SMTP account to send test emails and other email notifications to the users of this application. Not having the luxury to run my own SMTP server I decided that I would just temporarily use a Gmail (TM) account for sending the messages during development. It just so happens that Gmail uses Secure SMTP to send email messages and on top of that it requires the user to authenticate.

Java Libraries You Will Need

In further investigating this issue it turns out that pre Java Mail 1.4, there is no support for SMTPS Protocol. So we need to download the latest version at Java Mail.
  • Option #1:

    Download the latest Java Mail API jars.
    When using this route be warned that on the final click to download the java mail product you will be re-routed to install the Sun(TM) Download Manager. I am just really puzzled why Sun(TM) has the need to create their own download managers.

  • Option #2:

    Download the latest
    Java Platform Enterprise
    Edition
    and use the mail.jar that came with that product.

The particular class file that you want to check for in these jars are: com.sun.mail.smtp.SMTPSSLTransport.
Please note that for either options you will still need the Java Activation Framework (activation.jar).

JavaMailSenderImpl with Secure SMTP/SMTPS Support

In my own extension of the the JavaMailSenderImpl.java (see Source Code), it will automatically set the protocol to smtps and add Java Mail smtps properties if the property smtp.isSecure is set to true. Basically, the properties smtp host, username, password, and port will be required.  Also note the property smtp.isSecure is not a Java Mail property. It is just the property name that I came up with so that the code can toggle between normal smtp and smtps protocol.

I also created an override for the super.doSend(..) method so that after calling the Transport.connect(..) method, it will test for connection via the Transport.isConnected() method. This is just an extra step to make sure that we are connected to the SMTPS server and may not be needed in some cases.

Futhermore, If you have a CRUD for the server configuration,  the mail.properties value may be replaced with an implementation that retrieves its values from the database as well.

Update

The solution below now works using Spring 3.x version and Java Mail 1.4.5. The following Spring config is all you need to enable smtps.

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"
p:protocol="smtps" p:host="smtp.gmail.com" p:port="465"
p:username="morpheus@gmail.com" p:password="take-the-blue-pill" />


1 comment:

Ranjit Nayak said...

Nice analysis. We came to the same conclusion after hours of debugging. Your solution worked like a charm. Thanks.