Learn to send emails in Spring provided JavaMailSender
interface. Here is a step-by-step example of sending emails via Gmail SMTP server. We will use javax.mail
maven dependency to send emails while configuring mail properties in JavaMailSenderImpl
class that implements JavaMailSender
interface.
1. Maven
Follow maven project creation example for creating a new project. Now import Spring dependencies along with javax.mail.
<properties>
<spring.version>5.3.23</spring.version>
<email.version>1.6.2</email.version>
</properties>
<!-- Spring Context Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>${email.version}</version>
</dependency>
If we are using Spring boot, then we can help of its autoconfiguration feature by simply including the spring-boot-starter-mail starter.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
The starter template will transitively import the required jars in the project.
[INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.1.2.RELEASE:compile
[INFO] +- org.springframework:spring-context-support:jar:5.1.4.RELEASE:compile
[INFO] | \- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] \- com.sun.mail:javax.mail:jar:1.6.2:compile
[INFO] \- javax.activation:activation:jar:1.1:compile
2. Sending a SimpleMailMessage using JavaMailSender
2.1. Configuring JavaMailSenderImpl and Email Template
Given is Java configuration for JavaMailSender
which has been configured to use Gmail SMTP settings and we have configured a sample email template preconfigured with sender/receiver emails and email text.
We can further customize the configuration as per our needs.
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
@Configuration
public class EmailConfig
{
@Bean
public JavaMailSender getJavaMailSender()
{
JavaMailSender mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(25);
mailSender.setUsername("admin@gmail.com");
mailSender.setPassword("password");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}
@Bean
public SimpleMailMessage emailTemplate()
{
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("somebody@gmail.com");
message.setFrom("admin@gmail.com");
message.setText("FATAL - Application crash. Save your job !!");
return message;
}
}
2.2. Sending Email
The EmailService class uses the beans configured in applicationContext.xml file and uses them to send messages.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;
@Service("emailService")
public class EmailService
{
@Autowired
private JavaMailSender mailSender;
@Autowired
private SimpleMailMessage preConfiguredMessage;
/**
* This method will send compose and send a new message
* */
public void sendNewMail(String to, String subject, String body)
{
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(body);
mailSender.send(message);
}
/**
* This method will send a pre-configured message
* */
public void sendPreConfiguredMail(String message)
{
SimpleMailMessage mailMessage = new SimpleMailMessage(preConfiguredMessage);
mailMessage.setText(message);
mailSender.send(mailMessage);
}
}
3. Using JavaMailSender and MimeMessagePreparator
The recommended way of using JavaMailSender
interface is the MimeMessagePreparator
mechanism and using a MimeMessageHelper
for populating the message.
@Autowired
private JavaMailSender mailSender;
public void sendMail() {
MimeMessagePreparator messagePreparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
message.setFrom("me@mail.com");
message.setTo("you@mail.com");
message.setSubject("Mail subject");
message.setText("some text <img src='cid:logo'>", true);
message.addInline("logo", new ClassPathResource("img/logo.gif"));
message.addAttachment("myDocument.pdf", new ClassPathResource("uploads/document.pdf"));
}
};
mailSender.send(messagePreparator);
}
4. Mail Properties
We can configure the mail properties into application.properties file and inject using the @Value annotation.
spring.mail.host=smtp.gmail.com
spring.mail.port=25
spring.mail.username=admin@gmail.com
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.transport.protocol=smtp
spring.mail.properties.mail.smtp.starttls.enable=true
#Timeouts
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
If you are planning to use Amazon SES for sending emails, then you can use the following properties:
spring.mail.host=email-smtp.us-west-2.amazonaws.com
spring.mail.username=username
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.transport.protocol=smtp
spring.mail.properties.mail.smtp.port=25
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
5. Email Attachments and Inline Resources
It is easy to send simple mail messages containing only HTML, with no attachments or inline elements. However, inline elements and attachments are still a major compatibility issue between email clients.
Please use the appropriate MULTIPART_MODE and test the code thoroughly before pushing the code into production.
5.1. Email Attachments
To attach a file with email, use MimeMessageHelper
to attach the file with a MimeMessage
.
public void sendMailWithAttachment(String to, String subject, String body, String fileToAttach)
{
MimeMessagePreparator preparator = new MimeMessagePreparator()
{
public void prepare(MimeMessage mimeMessage) throws Exception
{
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
mimeMessage.setFrom(new InternetAddress("admin@gmail.com"));
mimeMessage.setSubject(subject);
mimeMessage.setText(body);
FileSystemResource file = new FileSystemResource(new File(fileToAttach));
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.addAttachment("logo.jpg", file);
}
};
try {
mailSender.send(preparator);
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
5.2. Inline Resources
Sometimes, we may want to attach inline resources such as inline images in email body. Inline resources are added to the MimeMessage by using the specified Content ID. Be sure first to add the text and then the resources. If you are doing it the other way around, it does not work.
public void sendMailWithInlineResources(String to, String subject, String fileToAttach)
{
MimeMessagePreparator preparator = new MimeMessagePreparator()
{
public void prepare(MimeMessage mimeMessage) throws Exception
{
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
mimeMessage.setFrom(new InternetAddress("admin@gmail.com"));
mimeMessage.setSubject(subject);
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true);
FileSystemResource res = new FileSystemResource(new File(fileToAttach));
helper.addInline("identifier1234", res);
}
};
try {
mailSender.send(preparator);
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
6. Demo
Time to test the spring mail sender program code. I am sending two messages from the test code. One is instantiated and composed in the test class itself, and the other is a pre-configured message from applicationContext.xml
file.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SpringEmailTest
{
public static void main(String[] args)
{
//Create the application context
ApplicationContext context = new FileSystemXmlApplicationContext
("classpath:com/howtodoinjava/core/email/applicationContext.xml");
//Get the mailer instance
EmailService mailer = (EmailService) context.getBean("emailService");
//Send a composed mail
mailer.sendMail("somebody@gmail.com", "Test Subject", "Testing body");
//Send a pre-configured mail
mailer.sendPreConfiguredMail("Exception occurred everywhere.. where are you ????");
}
}
The above call will send the emails.
Happy Learning !!
Comments