SpringBoot sends emails using the Thymeleaf template engine.

In this article, we will articulate and integrate the spring boot and thymeleaf template engine to make an email template and send the email.

Do a spring boot thymeleaf task for you by Kennymarlo08 | Fiverr

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. With modules for Spring Framework, a host of integrations with your favorite tools, and the ability to plug in your own functionality, Thymeleaf is ideal for modern-day HTML5 JVM web development — although there is much more it can do.

The above explanation about thymeleaf is from the official website.

Tech Stack:

  • Java 11
  • Tomcat
  • SpringBoot
  • Thymeleaf
  • maven

For now this much is fine.

Create Project:

To create project visit the http://start.spring.io/ and generate the project.

Download project and open it into any IDE or editor. I am using visual studio code. Here I am using maven as a build tool, you can use any one. Open the pom.xml file and check about the below dependencies.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.techwasti</groupId>
	<artifactId>thymeleafemailTemplate</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>thymeleafemailTemplate</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring5</artifactId>
		</dependency>

		
		<dependency>
			<groupId>nz.net.ultraq.thymeleaf</groupId>
			<artifactId>thymeleaf-layout-dialect</artifactId>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Below two dependencies are require.

thymeleaf-spring5 —Modern server-side Java template engine for both web and standalone environments

thymeleaf-layout-dialect -A dialect for Thymeleaf that allows you to use layout/decorator templates to style your content.

Properties change:

Now we have to add few properties in application.properties file or if you are using application.yaml file anything fine. Make sure below properties should be added.

spring.mail.default-encoding=UTF-8
spring.mail.host=smtp.gmail.com
[email protected]
spring.mail.password=yourpassword
spring.mail.port=587
spring.mail.protocol=smtp
spring.mail.test-connection=false
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

Define the Template:-

Thymeleaf is template engine library in java. We are using below features to design our email template.

  1. Flow control
  2. Spring EL
  3. Utility functions to format the data
  4. i18n integration
  5. Natural Templating

In this example, we are going to create a very simple HTML template. We should have to place the HTML template inside the resources/templates.

template file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Spring boot email template using Thymeleaf</title>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>

    <link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'/>

    <!-- use the font -->
    <style>
        body {
            font-family: 'Roboto', sans-serif;
            font-size: 48px;
        }
    </style>
</head>
<body>
<p th:text="${'Hello Dear ' + name}"></p>

<p th:if="${name.length() > 10}">
    Wow! You've got a long name (more than 10 chars)!
</p>
<p>
    You have been successfully subscribed to the <b>Techwasti newsletter</b> on
    <span th:text="${#dates.format(#dates.createNow(), 'dd MMM yyyy HH:mm')}"></span>
</p>

<p>
    You can find <b>your inlined image</b> just below this text.
</p>
<p>

    <a href="https://www.techwasti.com/">
        <img src="https://raw.githubusercontent.com/thymeleaf/thymeleaf-dist/master/src/artwork/thymeleaf%202016/thymeleaf_logo_white.png" alt="https://www.techwasti.com/" height="110" width="500"/>
    </a>
</p>
<p>
    Regards, <br />
    <em th:text="${sign}"></em>
<p th:text="${location}"></p>
</p>
</body>
</html>

Thymeleaf Configs:

Let us create new config package and create new class TemplateConfig.java. This class will help us to resolve the templates.

TemplateConfig.java

package com.techwasti.thymeleafemailTemplate.config;

import java.nio.charset.StandardCharsets;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Configuration
public class TemplateConfig {
    

    @Bean
    public SpringTemplateEngine springTemplateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.addTemplateResolver(htmlTemplateResolver());
        return templateEngine;
    }

    @Bean
    public ClassLoaderTemplateResolver htmlTemplateResolver(){
        ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
        emailTemplateResolver.setPrefix("/templates/");
        emailTemplateResolver.setSuffix(".html");
        emailTemplateResolver.setTemplateMode(TemplateMode.HTML);
        emailTemplateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        return emailTemplateResolver;
    }
}

here we haven’t hardcoded our template name, we just mentioned any file with .html extension from the templates folder. In order to process our templates, we will configure a SpringTemplateEngine which specially configured for email processing, in our Spring boot email template configuration. We need to tell Thymeleaf where the email templates are located.

EMail Service:

Create email service class that is triggering the email and sends email to recipients.

package service;

import org.springframework.stereotype.Service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.mail.javamail.JavaMailSender;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import com.techwasti.thymeleafemailTemplate.model.Mail;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Service
public class EmailSenderService {
    
    @Autowired
    private JavaMailSender emailSender;

    @Autowired
    private SpringTemplateEngine templateEngine;

    public void sendEmail(Mail mail) throws MessagingException, IOException {
        MimeMessage message = emailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message,
                MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
                StandardCharsets.UTF_8.name());

        String html = getHtmlContent(mail);

        helper.setTo(mail.getTo());
        helper.setFrom(mail.getFrom());
        helper.setSubject(mail.getSubject());
        helper.setText(html, true);

        emailSender.send(message);
    }

    private String getHtmlContent(Mail mail) {
        Context context = new Context();
        context.setVariables(mail.getHtmlTemplate().getProps());
        return templateEngine.process(mail.getHtmlTemplate().getTemplate(), context);
    }
}

Email Model:-

Email model is the DTO or model to hold the data and pass that to template.

Email.java

package com.techwasti.thymeleafemailTemplate.model;


import java.util.Map;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
public class Mail {

    @Getter
    @Setter
    public static class HtmlTemplate {
        private String template;
        private Map<String, Object> props;

        public HtmlTemplate(String template, Map<String, Object> props) {
            this.template = template;
            this.props = props;
        }
    }

    private String from;
    private String to;
    private String subject;
    private HtmlTemplate htmlTemplate;
}

Unit Test:-

Now everything is ready write down test code to make sure everything is working as expected.

package com.techwasti.thymeleafemailTemplate;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import service.EmailSenderService;
import javax.mail.MessagingException;

import com.techwasti.thymeleafemailTemplate.model.Mail;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.log4j.Log4j2;


@SpringBootTest
@Log4j2
class ThymeleafemailTemplateApplicationTests {

	@Autowired
	EmailSenderService senderService;

	@Test
	void contextLoads() throws Exception{

		log.info("sending sample email");

		Map<String, Object> properties = new HashMap<String, Object>();
		properties.put("name", "Maheshwar Ligade!");
		properties.put("location", "India");
		properties.put("sign", "Java Developer");

		Mail mail = Mail.builder()
				.from("[email protected]")
				.to("[email protected]")
				.htmlTemplate(new Mail.HtmlTemplate("sample", properties))
				.subject("This is sample email with spring boot and thymeleaf")
				.build();

		senderService.sendEmail(mail);
	}

}

Run the application check now the code.

Conclusion:-

We have discussed about the thymeleaf template that will help us to create the different template and send emails. For enterprise its bit hard to manage different email format for different domain and then for multiple language, but thymeleaf addressed this issue in very simple manner.

SourceCode:-

$ git clone https://github.com/maheshwarLigade/spring-boot-examples.git
$ cd thymeleafemailTemplate
$./mvnw spring-boot:run