Spring

Spring Mail: Inject SMTP Mail in Java

Introduction


All Java developers know, or should know, that the Spring framework contains a lot of gems. Recently I discovered a new gem: an easy way to send an email with Spring Mail. I’ve implemented the Spring Mail in one single POJO mail class, so you can easily let your application send an email and wire/inject all the mail configuration with the Spring applicationContext.xml.

Spring Mail Implementation


Let’s first look at the simple POJO mail class which implements the Spring Mail functionality:

package nl.amis.blog.mail;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;

@Configurable
public class MailMessage {

    @Autowired
    private MailSender mailSender;

    private final SimpleMailMessage message = new SimpleMailMessage();

    public MailMessage(final String from) {
        message.setFrom(from);
    }

    public MailMessage setReply(final String replyTo) {
        message.setReplyTo(replyTo);
        return this;
    }

    public MailMessage setTo(final String to) {
        message.setTo(to);
        return this;
    }

    public MailMessage setCc(final String cc) {
        message.setCc(cc);
        return this;
    }

    public MailMessage setBcc(final String bcc) {
        message.setBcc(bcc);
        return this;
    }

    public MailMessage setSubject(final String subject) {
        message.setSubject(subject);
        return this;
    }

    public MailMessage setBody(final String body) {
        message.setText(body);
        return this;
    }

    public void send() {
        mailSender.send(message);
    }
}

The Java class only contains setters for the mail properties and one method, the send method, to send the mail.
All the setters are delegated (composition pattern [1]) to the SimpleMailMessage class provided by the Spring framework and return the current instance implementing the builder pattern [2].
The send method sends the mail using the MailSender which is also part of the Spring Mail framework.

This results in nice clean code when using it:

MailMessage message = new MailMessage("abc.def@gmail.com").setTo("ghi.jkl@gmail.com");
message.setSubject("Hello").setBody("Hello World!").send();

Spring Mail Configuration


The only remainder thing to do is wiring the mail configuration (smtp settings) to the Spring MailSender class in the Spring applicationContext.xml. I’ve chosen to read them from a separate properties file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"              xmlns:context="http://www.springframework.org/schema/context" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >

  <context:annotation-config />
  <context:spring-configured />
  <context:load-time-weaver />
  <context:component-scan base-package="nl.amis.blog.mail" />

  <context:property-placeholder location="file:${oracle.j2ee.home}/config/myApp.properties" />

  <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host">
      <value>${mail.smtp.host.name}</value>
    </property>
    <property name="port">
      <value>${mail.smtp.host.port}</value>
    </property>
    <property name="username">
      <value>${mail.smtp.username}</value>
    </property>
    <property name="password">
      <value>${mail.smtp.password}</value>
    </property>
    <property name="javaMailProperties">
      <props>
        <!-- Use SMTP transport protocol -->
        <prop key="mail.transport.protocol">smtp</prop>
        <!-- Use SMTP-AUTH to authenticate to SMTP server -->
        <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
        <!-- Use TLS to encrypt communication with SMTP server -->
        <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
        <prop key="mail.debug">${mail.debug}</prop>
      </props>
    </property>
  </bean>
</beans>

The relevant part of the properties file looks like this:

# Hostname of mail server
mail.smtp.host.name= ABC001
# Port nr of mail server
mail.smtp.host.port= 25
# Username to connect to mailserver (can be empty for anonymous connection)
mail.smtp.username=
# Password to connect to mailserver (can be empty for anonymous connection)
mail.smtp.password=
# Switch authorisation on (true) or off (false)
mail.smtp.auth= false
# Switch TLS encryption on (true) or off (false)
mail.smtp.starttls.enable = false
# Switch debug logging of spring mailcomponent on (true) or off (false)
mail.debug= true

Dependency on AspectJ


Note that using the @Configurable annotation, also Spring loadtime waving is used. This is needed to be able to inject into a POJO at creation time with AspectJ. This means that the Spring loadtime waving jars have to be added besides the normal Spring library jars:

  • org.aspectj.aspectjweaver-x.y.z.jar
  • org.aspectj.aspectjrt-x.y.z.jar
  • org.springframework.spring-aspects-x.y.z.jar

Don’t forget to include the loadtime waving configuration tags in the Spring applicationContext.xml where the component-scan tag defines which packages have to be scanned for loadtime waving (you don’t want to scan all your jar libraries).

[1] Item 16: Favor composition over inheritance – Effective Java 2nd Edition – Joshua Bloch
[2] Item 2: Consider a builder when faced with many constructor parameters – Effective Java 2nd Edition – Joshua Bloch