SMTP: Spring Mail To Program
All Java developers know, or should know, the Spring framework contains a lot of gems. Recently I discovered a new gem: an easy way to send an email. With the use of one single POJO mail class, you can easily let your application send an email and wire/inject al the mail configuration with the Spring applicationContext.xml.
Let’s first look at the simple POJO mail class.
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);
}
}
It only contains setters for the mail properties and one method, the send method.
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 real mail using the MailSender which is also part of the Spring 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();
The only 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>
So part of my 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
Note that using the @Configurable annotation, Spring loadtime waving is used. This is needed to be able to inject in a POJO at creation 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