Spring 4 Email Integration Tutorial

Spring provides first-class support for sending Emails. Spring comes with utility libraries which abstracts away the complexities of the underlying mailing system, provides super-simple API to use in your application to send emails. Let’s get going.


Spring Email support is built upon JavaMail API, which must be found on class path. In our example, we did so by including APIjavax.mail.javax.mail-api & implementation javax.mail.mail in our pom.xml. Spring’s EMail support related stuff is packaged under spring-context-support.

Below is the pom.xml for this post.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.websystique.spring</groupId>
	<artifactId>SpringEmailExample</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<name>SpringEmailExample</name>

	<properties>
		<springframework.version>4.3.0.RELEASE</springframework.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<!-- All Mail related stuff + Much more-->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<!-- JavaMail-->
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>javax.mail-api</artifactId>
			<version>1.5.5</version>
		</dependency>
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4.7</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Spring provides two primary interfaces for sending emails:

  • MailSender : handy for sending simple mail messages, providing ‘from’,’to’,’cc’,’bcc’,’subject’ & other mail properties.
  • JavaMailSender : Extends MailSender, adds specialized JavaMail features such as MIME message support.

Spring’s JavaMailSenderImpl is production implementation of the JavaMailSender interface which can be used for host configuration as well as connection setup. Shown below is our configuration class, using Gmail SMTP connection settings to send emails using gmail.

package com.websystique.spring.configuration;

import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

@Configuration
@ComponentScan(basePackages = "com.websystique.spring")
public class AppConfig {
	
	//Put Other Application configuration here.
	
	@Bean
	public JavaMailSender getMailSender(){
		JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
		
		//Using gmail
		mailSender.setHost("smtp.gmail.com");
		mailSender.setPort(587);
		mailSender.setUsername("Your-gmail-id");
		mailSender.setPassword("Your-gmail-password");
		
		Properties javaMailProperties = new Properties();
		javaMailProperties.put("mail.smtp.starttls.enable", "true");
		javaMailProperties.put("mail.smtp.auth", "true");
		javaMailProperties.put("mail.transport.protocol", "smtp");
		javaMailProperties.put("mail.debug", "true");//Prints out everything on screen
		
		mailSender.setJavaMailProperties(javaMailProperties);
		return mailSender;
	}
}

You should adapt above configuration based on your Email provider settings and credentials. Once you got JavaMailSender ready, only thing left is to prepare the actual message itself and then send it using JavaMailSender.

To prepare the message itself, spring provides[among several other possibilities] a handy Callback MimeMessagePreparator interface, which can be used for the preparation of JavaMail MIME messages. This preparator can then be passed to javaMailSender while calling send to actually send the message.

Spring also provides possibilities to send Attachment and inline content with Email.Post Send Attachment + Inline content with Email using Spring 4 contains an example for the same. You can even create a specific Email template for your application, and include that in all your messages. Post Spring 4 Email Tutorial using Velocity/Freemarker Templates shows that in action.

Below is the mail-sending logic. Take special note of recipient, which is the email id of recipient.

package com.websystique.spring.service;

import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;

import com.websystique.spring.model.ProductOrder;

@Service("mailService")
public class MailServiceImpl implements MailService {

	@Autowired
	JavaMailSender mailSender;

	@Override
	public void sendEmail(Object object) {

		ProductOrder order = (ProductOrder) object;

		MimeMessagePreparator preparator = getMessagePreparator(order);

		try {
			mailSender.send(preparator);
			System.out.println("Message Send...Hurrey");
		} catch (MailException ex) {
			System.err.println(ex.getMessage());
		}
	}

	private MimeMessagePreparator getMessagePreparator(final ProductOrder order) {

		MimeMessagePreparator preparator = new MimeMessagePreparator() {

			public void prepare(MimeMessage mimeMessage) throws Exception {
				mimeMessage.setFrom("customerserivces@yourshop.com");
				mimeMessage.setRecipient(Message.RecipientType.TO,
						new InternetAddress(order.getCustomerInfo().getEmail()));
				mimeMessage.setText("Dear " + order.getCustomerInfo().getName()
						+ ", thank you for placing order. Your order id is " + order.getOrderId() + ".");
				mimeMessage.setSubject("Your order on Demoapp");
			}
		};
		return preparator;
	}

}

Let’s write a Main to actually see the email sending in action. Shown below is the Main for this example:

package com.websystique.spring.configuration;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.model.CustomerInfo;
import com.websystique.spring.model.ProductOrder;
import com.websystique.spring.service.OrderService;

public class SampleEmailApplication {

	public static void main(String[] args) {
		AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		OrderService orderService = (OrderService) context.getBean("orderService");
		orderService.sendOrderConfirmation(getDummyOrder());
		((AbstractApplicationContext) context).close();
	}
	
	public static ProductOrder getDummyOrder(){
		ProductOrder order = new ProductOrder();
		order.setOrderId("1111");
		order.setProductName("Thinkpad T510");
		order.setStatus("confirmed");
		
		CustomerInfo customerInfo = new CustomerInfo();
		customerInfo.setName("Websystique Admin");
		customerInfo.setAddress("WallStreet");
		customerInfo.setEmail("websystique@gmail.com");
		order.setCustomerInfo(customerInfo);
		return order;
	}

}

Build & Execute

Run the mail program, and check your [customer] mailbox. You should see new message.

SpringEmail_img1

And the execution logs are:

Jul 05, 2016 12:22:53 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4ec4f498: startup date [Tue Jul 05 00:22:53 CEST 2016]; root of context hierarchy
DEBUG: JavaMail version 1.5.5
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
220 smtp.gmail.com ESMTP t67sm6893011wma.1 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 587

EHLO 192.168.1.3
250-smtp.gmail.com at your service, [81.243.87.175]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
EHLO 192.168.1.3
250-smtp.gmail.com at your service, [81.243.87.175]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<customerserivces@yourshop.com>
250 2.1.0 OK t67sm6893011wma.1 - gsmtp
RCPT TO:<websystique@gmail.com>
250 2.1.5 OK t67sm6893011wma.1 - gsmtp
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   websystique@gmail.com
DATA
354  Go ahead t67sm6893011wma.1 - gsmtp
Date: Tue, 5 Jul 2016 00:22:57 +0200 (CEST)
From: customerserivces@yourshop.com
To: websystique@gmail.com
Message-ID: <68026518.0.1467670977746@dragon>
Subject: Your order on Demoapp
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Dear Websystique Admin, thank you for placing order. Your order id is 1111.
.
250 2.0.0 OK 1467670979 t67sm6893011wma.1 - gsmtp
QUIT
221 2.0.0 closing connection t67sm6893011wma.1 - gsmtp
Message Send...Hurrey
Jul 05, 2016 12:22:59 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@4ec4f498: startup date [Tue Jul 05 00:22:53 CEST 2016]; root of context hierarchy
Important: In case you are getting problems while connecting to Gmail, check first if you have two step security enabled in your gmail. Additionally, check if you have received an email from provider[gmail] saying “Sign-in attempt prevented”. If yes, there will be instruction in that email on how to allow/disallow less secured apps to access your mail provider [Turn on/off access to less secured apps].

That’s it. For the sake of completeness, shown below are the remaining classes from this example.

package com.websystique.spring.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.websystique.spring.model.ProductOrder;

@Service("orderService")
public class OrderServiceImpl implements OrderService{

	@Autowired
	MailService mailService;

	@Override
	public void sendOrderConfirmation(ProductOrder productOrder) {
		mailService.sendEmail(productOrder);
	}
	
}

package com.websystique.spring.service;

import com.websystique.spring.model.ProductOrder;

public interface OrderService {

	public void sendOrderConfirmation(ProductOrder productOrder);
	
}

package com.websystique.spring.service;

public interface MailService {

	public void sendEmail(final Object object);
}

package com.websystique.spring.model;

public class CustomerInfo {

	private String name;
	
	private String address;
	
	private String email;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "CustomerInfo [name=" + name + ", address=" + address + ", email=" + email + "]";
	}
	
}

package com.websystique.spring.model;


public class ProductOrder {
	
	private String orderId;
	
	private String productName;

	private String status;
	
	private CustomerInfo customerInfo;
	
	public String getOrderId() {
		return orderId;
	}

	public void setOrderId(String orderId) {
		this.orderId = orderId;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public CustomerInfo getCustomerInfo() {
		return customerInfo;
	}

	public void setCustomerInfo(CustomerInfo customerInfo) {
		this.customerInfo = customerInfo;
	}

	@Override
	public String toString() {
		return "ProductOrder [orderId=" + orderId + ", productName=" + productName + ", status=" + status
				+ ", customerInfo=" + customerInfo + "]";
	}

	
}

And finally the directory structure.
SpringEmail_img2

That’s it. As we saw, it’s rather easy to use Spring’s email support in your own application. Feel free to comment, and suggest improvements.

Download Source Code


References