As part of the Spring Boot tutorial, in this article, we will see how to send email using Spring.
Introduction
Sending out email is a typical need for any application. In this article will learn the steps to send email using Spring. To work on this tutorial, you need SMTP details to send out the email. For the sample application, you can use Gmail smtp (keep in mind Gmail have a certain limitation on the email quota). The Spring Framework provides an easy abstraction for sending email by using the JavaMailSender interface, and Spring Boot provides auto-configuration for it and a starter module.
1. Maven Dependencies
We need to add the spring-boot-starter-mail in our pom.xml to enable Spring Boot auto-configuration for our application. This is the snapshot of our pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2. Mail Configurations
Once we have the dependencies defined, the next step is to add the mail configurations to be available to Spring Boot auto configuration:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username= gmail user name
spring.mail.password= your password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Above configurations values are for Gmail SMTP, replace these with your SMTP configurations:
3. Email Service
Let’s create a simple email service class to send out emails for our application. Our sample email service will contain 2 method:
- Send out simple emails
- Emails with attachment
This is how our code look like:
@Service
public class DefaultEmailService implements EmailService {
@Autowired
public JavaMailSender emailSender;
@Override
public void sendSimpleEmail(String toAddress, String subject, String message) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo(toAddress);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(message);
emailSender.send(simpleMailMessage);
}
@Override
public void sendEmailWithAttachment(String toAddress, String subject, String message, String attachment) throws MessagingException, FileNotFoundException {
MimeMessage mimeMessage = emailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setTo(toAddress);
messageHelper.setSubject(subject);
messageHelper.setText(message);
FileSystemResource file = new FileSystemResource(ResourceUtils.getFile(attachment));
messageHelper.addAttachment("Purchase Order", file);
emailSender.send(mimeMessage);
}
}
4. Test Controller
Let’s create a simple REST controller to check our work. Our REST controller will have 2 methods. This is how our controller look like:
package com.javadevjournal.controller;
import com.javadevjournal.email.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.MailException;
import org.springframework.web.bind.annotation.*;
import javax.mail.MessagingException;
import java.io.FileNotFoundException;
@RestController
@RequestMapping("/email")
public class EmailController {
private static final Logger LOG = LoggerFactory.getLogger(EmailController.class);
@Autowired
EmailService emailService;
@GetMapping(value = "/simple-email/{user-email}")
public @ResponseBody ResponseEntity sendSimpleEmail(@PathVariable("user-email") String email) {
try {
emailService.sendSimpleEmail(email, "Welcome", "This is a welcome email for your!!");
} catch (MailException mailException) {
LOG.error("Error while sending out email..{}", mailException.getStackTrace());
return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>("Please check your inbox", HttpStatus.OK);
}
@GetMapping(value = "/simple-order-email/{user-email}")
public @ResponseBody ResponseEntity sendEmailAttachment(@PathVariable("user-email") String email) {
try {
emailService.sendEmailWithAttachment(email, "Order Confirmation", "Thanks for your recent order",
"classpath:purchase_order.pdf");
} catch (MessagingException | FileNotFoundException mailException) {
LOG.error("Error while sending out email..{}", mailException.getStackTrace());
return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>("Please check your inbox for order confirmation", HttpStatus.OK);
}
}
5. Spring Boot Main Class
@SpringBootApplication
public class SendEmailUsingSpringApplication {
public static void main(String[] args) {
SpringApplication.run(SendEmailUsingSpringApplication.class, args);
}
}
Run our application and hit the following URL‘s :
http://localhost:8080/email/order-email/[email protected]
http://localhost:8080/email/simple-email/[email protected]
6. Gmail SMTP
If you are using Gmail SMTP, please refer to the following URL for detail. Your normal email password will not work because of added security in Gmail.
How to Send Email using Spring Boot and Thymeleaf
In the pervious section, we saw steps to send emails using Spring, however for a production application, we need a more powerful way to send out emails. In this section, we will look at how to send emails using Spring Boot and Thyleleaf.
Thyleleaf is a template engine. Thymeleaf can help us send rich HTML emails. Let’s assume that we want to send account verification confirmation email to the customer.
7. EmailContext Class
To make it more flexible, we will create EmailContext class which will holds all the core information we need for email. This is how our class look like:
public abstract class AbstractEmailContext {
private String from;
private String to;
private String subject;
private String email;
private String attachment;
private String fromDisplayName;
private String emailLanguage;
private String displayName;
private String templateLocation;
private Map <String, Object> context;
//getter and seter methods
}
Let’s talk about few fields in this class:
templateLocation
– Specify the location of our HTML template. We will use this to generate the final output.context
– This contains all the dynamic values passed in the email. Thymeleaf will use this map to replace the expressions with the actual values (e.g. Your first name etc.)
Next we will change our Email service to process the Thymeleaf HTML templates to generate email content.
8. EmailService
package com.javadevjournal.core.email.service;
import com.javadevjournal.core.email.context.AbstractEmailContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.nio.charset.StandardCharsets;
@Service
public class DefaultEmailService implements EmailService {
@Autowired
private JavaMailSender emailSender;
@Autowired
private SpringTemplateEngine templateEngine;
@Override
public void sendMail(AbstractEmailContext email) throws MessagingException {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
Context context = new Context();
context.setVariables(email.getContext());
String emailContent = templateEngine.process(email.getTemplateLocation(), context);
mimeMessageHelper.setTo(email.getTo());
mimeMessageHelper.setSubject(email.getSubject());
mimeMessageHelper.setFrom(email.getFrom());
mimeMessageHelper.setText(emailContent, true);
emailSender.send(message);
}
}
There are few important things happening in the above code.
- We are creating and setting the map as variables. Thymeleaf will use this context to replace the placeholder or expressions with the values passed through context.
SpringTemplateEngine
is an abstraction around different template engine and will pick the configured template engine. In our case, it is Thymeleaf.- The
templateEngine.process()
will process and provide an output as String. This will pick the HTML template, process it, and replace the expressions with actual values. - Finally, we set that content in the
MimeMessage
and telling the mail server to treat these content as HTML (mimeMessageHelper.setText(emailContent, true)
)
9. Email Template
Here is our HTML template for the email (I have taken out some HTML to save some space).
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8"> <!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting"> <!-- Disable auto-scale in iOS 10 Mail entirely -->
<title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
<!-- CSS Reset : BEGIN -->
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌
</div>
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="logo" style="text-align: center;">
<h1>Welcome</h1>
</td>
</tr>
</table>
</td>
</tr><!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>Finish creating your account.</h2>
<h3>Hi<p th:text="${firstName}"></h3>
<h3>We're excited to have you get started. First, you need to confirm your account. Just press the button below.</h3>
<p><a th:href="${verificationURL}" class="btn btn-primary">Validate Account</a></p>
</div>
</td>
</tr>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h3>if you experience any issues with the button above, copy and paste the URL below into your web browser.</h3>
<p th:text="${verificationURL}"></p>
</div>
</td>
</tr>
</table>
</td>
</tr><!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>Welcome to Java Development Journal Blog. We publish articles on
Spring, Spring Boot and Spring Security.
</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text">Java Development Journal</span></li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr><!-- end: tr -->
</table>
</div>
</center>
</body>
</html>
Keep in mind that we need to provide the value for ${firstName}
and ${verificationURL}
in the context so as Thymeleaf can inject the actual value for these variables during processing.
Summary
In this article, we learned how to send email using Spring. We saw how to use Spring Boot auto-configuration to make it more flexible for the email functionality. The source code for this post is available on GitHub.