Simplifying Email Templating with Thymeleaf and Spring Boot

Gagan Chordia
4 min readAug 29, 2023

--

Before getting started, let’s find out about Spring Mail & Thymeleaf

What is Spring Mail?

The Spring Framework provides a helpful utility library for sending email that shields the user from the specifics of the underlying mailing system and is responsible for low level resource handling on behalf of the client.

What is Thymeleaf?

Thymeleaf is a modern server-side Java template engine for both web and standalone environments. Thymeleaf’s main goal is to bring elegant natural templates to your development workflow — HTML that can be correctly displayed in browsers and also work as static prototypes, allowing for stronger collaboration in development teams.

Where can we use Thymeleaf?

Thymeleaf can be used for both web and non-web applications.

  • Web Views,
  • PDF Templates,
  • Email Templates,
  • CSV Templates,
  • API Documentation,
  • etc.

Why do we need Thymeleaf for Mailing?

  1. Templating: Thymeleaf provides a flexible way to create HTML templates with placeholders for dynamic data. This enables you to create consistent and visually appealing email layouts that can include images, styles, and other HTML elements.
  2. HTML Escaping: Thymeleaf automatically escapes HTML content, helping to prevent cross-site scripting (XSS) vulnerabilities when injecting dynamic content into email templates.
  3. Ease of Use: Thymeleaf uses familiar HTML syntax, which makes it approachable for developers who are already comfortable with web development technologies.
  4. Dynamic Content: Thymeleaf allows you to easily inject dynamic content into email templates.
  5. Fragment Reuse: Thymeleaf lets you define reusable fragments or components that you can include in multiple templates.

Let’s begin with the demo

Initializing the app

  1. Go to https://start.spring.io or use Spring Initializer Plugin from your IDE.
  2. Fill the project details.
  3. Add the following dependencies: Spring Boot Dev Tools, Spring Web, Java Mail Sender, Thymeleaf and Lombok.
  4. Generate & extract the project.

Setting App Password using Gmail

  1. Go to accounts.google.com and search for App Passwords.
  2. Verify the account by logging in.
  3. Under select app drop-down, choose Other. Then enter your app name, in my case, DemoAppExample.
  4. You will get a 16-letter password. Note the password on a notepad.

Configuring the app

Add the following code to application.properties file.

spring.mail.host=smtp.google.com
spring.mail.port=587
spring.mail.username=youremail@gmail.com
spring.mail.password=your-app-password-from-previous-step (Without spaces or any special character)
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.mime.charset=UTF

Configuring Thymeleaf

In project file create a folder, named configurations or config and add ThymeleafConfig.java file to it.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Configuration
public class ThymeleafConfig implements WebMvcConfigurer {
@Bean
public ClassLoaderTemplateResolver templateResolver() {
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();

resolver.setPrefix("templates/"); // Location of thymeleaf template
resolver.setCacheable(false); // Turning of cache to facilitate template changes
resolver.setSuffix(".html"); // Template file extension
resolver.setTemplateMode("HTML"); // Template Type
resolver.setCharacterEncoding("UTF-8");

return resolver;
}

@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());

return engine;
}
}

Creating a Thymeleaf base template

Create an HTML file in the following directory: /resources/templates/ and add the following code.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<!--
HTML code would be added to the below div tag
which would be taken as an input from the user.
-->
<div th:utext="${content}"></div>
</body>
</html>

Creating a Data Transfer Object (DTO)

Creating a DTO can help us to take mail contents from the frontend as a request.

In project file create a folder, named dto and add MailRequest.java file to it.

import com.fasterxml.jackson.annotation.JsonAlias;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MailRequest {
@JsonAlias(value = "to_email")
private String toEmail;

private String subject;

private String message;

@JsonAlias(value = "html")
private boolean isHTML;
}

Create an Email Service

In project file create a folder, named service and add EmailingService.java file to it.

import com.example.demo.dto.MailRequest;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;

import lombok.RequiredArgsConstructor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

@Service
@RequiredArgsConstructor
public class EmailingService {
private final JavaMailSender mailSender;
private final TemplateEngine templateEngine;

@Value("${spring.mail.username}")
private String fromMail;

@Async
public void sendMail(MailRequest request) throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage);

mimeMessageHelper.setFrom(fromMail);
mimeMessageHelper.setTo(request.getToEmail());
mimeMessageHelper.setSubject(request.getSubject());

if(request.isHTML()) {
Context context = new Context();
/*
content is the variable defined in our HTML template within the div tag
*/
context.setVariable("content", request.getMessage());
String processedString = templateEngine.process("template", context);

mimeMessageHelper.setText(processedString, true);
} else {
mimeMessageHelper.setText(request.getMessage(), false);
}

mailSender.send(mimeMessage);
}
}

Create Email Controller

In project file create a folder, named controller and add EmailingController.java file to it.

import com.example.demo.dto.MailRequest;
import com.example.demo.service.EmailingService;

import jakarta.mail.MessagingException;

import lombok.RequiredArgsConstructor;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/mail")
public class EmailingController {
private final EmailingService emailingService;

@PostMapping
@ResponseStatus(HttpStatus.OK)
public void sendMail(@RequestBody MailRequest request) throws MessagingException {
emailingService.sendMail(request);
}
}

Testing

I would be using Postman to test the API

Output:

Conclusion

With the above setup, one would be able to access Spring Mail & Thymeleaf to its potential to send custom mails and integrate multiple features.
Happy Coding 😊!!

--

--

Gagan Chordia
Gagan Chordia

Written by Gagan Chordia

Spring Boot | Java | Vue.js | R

No responses yet