Using Spring Boot and Thymeleaf, it’s easy to send HTML emails to your users. This post will show the configuration and logic to send an email. We won’t go into details on how to setup the template, that’s for another time.
Project setup
Assuming you already use Spring Boot, we need to add two dependencies for this to work. The first is spring-boot-starter-mail, for sending the email. The second is spring-boot-starter-thymeleaf for handling the HTML template that we are going to use.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Email configuration
We need to configure two beans. To send the email, we’re going to use Spring’s JavaMailSender. To resolve the template. we’re going to use Thymeleaf’s TemplateResolver. Since both beans are specifically configured for sending emails, we configure them in the same class.
JavaMailSender configuration
We need to create a properties file containing the mail server configuration. Let’s put it in src/main/resources/email/emailconfig.properties
email.host=mail.server.address email.username=username email.password=password
Next we’ll create the EmailConfiguration class.
@Configuration @PropertySource("classpath:/email/emailconfig.properties") public class EmailConfiguration { @Value("${email.host}") private String host; @Value("${email.username}") private String username; @Value("${email.password}") private String password; }
Using @PropertySource we reference the properties file we created earlier. The @Value annotation is used to reference the property in the properties file.
Let’s configure the JavaMailSender bean next.
@Bean public JavaMailSender getJavaMailSender() { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost(host); mailSender.setPort(25); mailSender.setUsername(username); 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; }
This sets up a JavaMailSender configured to use the smtp protocol. It’s mostly self explanatory.
TemplateEngine configuration
To resolve and process the template, we need to configure a separate TemplateEngine. This TemplateEngine will only use one TemplateResolver. You could configure more if you need to.
@Bean public TemplateEngine emailTemplateEngine(){ final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.addTemplateResolver(templateResolver()); return templateEngine; } private ITemplateResolver templateResolver() { final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setOrder(Integer.valueOf(1)); templateResolver.setResolvablePatterns(Collections.singleton("*")); templateResolver.setPrefix("/email/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode(TemplateMode.HTML); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setCacheable(false); return templateResolver; } }
This TemplateResolver will look for templates in src/main/resources/email, with a name ending in .html. It will handle the file as an HTML file.
Email service
Now that the beans are configured, we’re going to create a service that actually sends the email.
@Log @Service public class EmailService { public static final String SENDER_ADDRESS = "from@email.com"; public static final String SUBJECT = "Subject of the email"; private final TemplateEngine templateEngine; private final JavaMailSender emailSender; @Autowired public EmailService(JavaMailSender emailSender, TemplateEngine emailTemplateEngine){ this.templateEngine = emailTemplateEngine; this.emailSender = emailSender; } public void send(Context context, String template, String address, String senderAddress, String subject){ try { final MimeMessage mimeMessage = this.emailSender.createMimeMessage(); final MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, "UTF-8"); messageHelper.setFrom(senderAddress); messageHelper.setTo(address); messageHelper.setSubject(subject); final String htmlContent = this.templateEngine.process(template, context); messageHelper.setText(htmlContent, true); emailSender.send(mimeMessage); } catch (MessagingException e){ log.warning(e.getMessage()); } } }
One thing to note here is the Context, which contains the data Thymeleaf uses to fill out the template. The ’template’ parameter contains the filename of the template to use, e.g. ‘email.html’. This file needs to be placed where the TemplateResolver will look, in src/main/resources/email.