Перейти к основному содержимому

Использование шаблонов электронной почты ThymeLeaf и FreeMarker с Spring

· 6 мин. чтения

1. Обзор

В нашей предыдущей статье мы увидели, как использовать Spring для написания и отправки текстовых электронных писем.

Но также можно использовать механизмы шаблонов Spring для написания красивых электронных писем в формате HTML с динамическим содержимым .

В этом уроке мы узнаем, как это сделать, используя самые известные из них: Thymeleaf и FreeMarker .

2. Весенние электронные письма в формате HTML

Начнем с учебника Spring Email .

Во-первых, мы добавим в класс EmailServiceImpl метод для отправки электронных писем с телом HTML:

private void sendHtmlMessage(String to, String subject, String htmlBody) throws MessagingException {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlBody, true);
emailSender.send(message);
}

Мы используем MimeMessageHelper для заполнения сообщения . Важной частью является истинное значение, передаваемое методу setText : оно определяет тип содержимого HTML.

Давайте теперь посмотрим, как создать этот htmlBody, используя шаблоны Thymeleaf и FreeMarker.

3. Конфигурация листа тимьяна

Начнем с конфигурации. Мы можем изолировать это в классе под названием EmailConfiguration .

Во- первых, мы должны предоставить распознаватель шаблонов для поиска каталога файлов шаблонов .

3.1. Шаблоны как ресурсы пути к классам

Файлы шаблонов могут быть отправлены в файле JAR , что является самым простым способом обеспечения согласованности между шаблонами и их входными данными.

Чтобы найти шаблоны из JAR, мы используем ClassLoaderTemplateResolver . Наши шаблоны находятся в каталоге main/resources/mail-templates , поэтому мы устанавливаем атрибут Prefix относительно каталога ресурсов :

@Bean
public ITemplateResolver thymeleafTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("mail-templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}

3.2. Шаблоны из внешнего каталога

В других случаях мы можем захотеть изменить шаблоны без пересборки и развертывания . Для этого мы можем поместить шаблоны в файловую систему.

Может быть полезно настроить этот путь в application.properties , чтобы мы могли изменять его для каждого развертывания. Доступ к этому свойству можно получить с помощью аннотации @Value :

@Value("${spring.mail.templates.path}")
private String mailTemplatesPath;

Затем мы передаем это значение в FileTemplateResolver вместо ClassLoaderTemplateResolver в нашем методе thymeleafTemplateResolver :

FileTemplateResolver templateResolver = new FileTemplateResolver();
templateResolver.setPrefix(mailTemplatesPath);

3.3. Настройте движок Thymeleaf

Последним шагом является создание фабричного метода для движка Thymeleaf. Нам нужно сообщить движку, какой TemplateResolver мы выбрали, который мы можем внедрить через параметр в метод фабрики компонентов:

@Bean
public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
templateEngine.setTemplateEngineMessageSource(emailMessageSource());
return templateEngine;
}

Здесь созданный ранее преобразователь автоматически внедряется Spring в фабричный метод механизма шаблонов.

4. Конфигурация FreeMarker

Так же, как и Thymeleaf, в классе EmailConfiguration мы настроим преобразователь шаблонов для шаблонов FreeMarker (.ftl ) :

и на этот раз расположение шаблонов будет настроено в bean -компоненте FreeMarkerConfigurer .

4.1. Шаблоны в пути к классам

Здесь у нас те же параметры, что и для Thymeleaf. Давайте настроим шаблоны как ресурсы пути к классам:

@Bean 
public FreeMarkerConfigurer freemarkerClassLoaderConfig() {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_27);
TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/mail-templates");
configuration.setTemplateLoader(templateLoader);
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setConfiguration(configuration);
return freeMarkerConfigurer;
}

4.2. Шаблоны в файловой системе

Чтобы настроить шаблоны из другого пути в файловой системе, нам нужно заменить экземпляр TemplateLoader :

TemplateLoader templateLoader = new FileTemplateLoader(new File(mailTemplatesPath));

5. Локализация с помощью Thymeleaf и FreeMarker

Чтобы управлять переводами с Thymeleaf, мы можем указать экземпляр MessageSource для движка :

@Bean
public ResourceBundleMessageSource emailMessageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("mailMessages");
return messageSource;
}
@Bean
public SpringTemplateEngine thymeleafTemplateEngine() {
...
templateEngine.setTemplateEngineMessageSource(emailMessageSource());
...
}

Затем мы создадим пакеты ресурсов для каждой поддерживаемой локали:

src/main/resources/mailMessages_xx_YY.properties

Поскольку FreeMarker предлагает локализацию путем дублирования шаблонов , нам не нужно настраивать там источник сообщений.

6. Содержание шаблонов Thymeleaf

Далее давайте посмотрим на файл template-thymeleaf.html :

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="#{greetings(${recipientName})}"></p>
<p th:text="${text}"></p>
<p th:text="#{regards}"></p>
<p>
<em th:text="#{signature(${senderName})}"></em> <br />
</p>
</body>
</html>

Как видно, мы использовали нотацию Thymeleaf, то есть ${…} для переменных и #{…} для локализованных строк .

Поскольку механизм шаблонов настроен правильно, использовать его очень просто: мы просто создадим объект Context , который содержит переменные шаблона (здесь они передаются как карта ).

Затем мы передадим его методу процесса вместе с именем шаблона:

@Autowired
private SpringTemplateEngine thymeleafTemplateEngine;

@Override
public void sendMessageUsingThymeleafTemplate(
String to, String subject, Map<String, Object> templateModel)
throws MessagingException {

Context thymeleafContext = new Context();
thymeleafContext.setVariables(templateModel);
String htmlBody = thymeleafTemplateEngine.process("template-thymeleaf.html", thymeleafContext);

sendHtmlMessage(to, subject, htmlBody);
}

Теперь давайте посмотрим, как сделать то же самое с FreeMarker.

7. Содержимое шаблонов FreeMarker

Как видно, синтаксис FreeMarker проще, но опять же он не работает с локализованными строками. Итак, вот английская версия:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Hi ${recipientName}</p>
<p>${text}</p>
<p>Regards,</p>
<p>
<em>${senderName} at ForEach</em> <br />
</p>
</body>
</html>

Затем мы должны использовать класс FreeMarkerConfigurer для получения файла шаблона и, наконец, FreeMarkerTemplateUtils для вставки данных из нашей карты :

@Autowired
private FreeMarkerConfigurer freemarkerConfigurer;

@Override
public void sendMessageUsingFreemarkerTemplate(
String to, String subject, Map<String, Object> templateModel)
throws IOException, TemplateException, MessagingException {

Template freemarkerTemplate = freemarkerConfigurer.getConfiguration()
.getTemplate("template-freemarker.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel);

sendHtmlMessage(to, subject, htmlBody);
}

Чтобы пойти дальше, мы увидим, как добавить логотип в нашу подпись электронной почты.

8. Электронные письма со встроенными изображениями

Поскольку очень часто изображения включаются в сообщения электронной почты в формате HTML, мы рассмотрим, как это сделать с помощью вложения CID .

Первое изменение касается метода sendHtmlMessage . Мы должны установить MimeMessageHelper как состоящую из нескольких частей , передав true второму аргументу конструктора:

MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

Затем мы должны получить файл изображения в качестве ресурса. Для этого мы можем использовать аннотацию @Value :

@Value("classpath:/mail-logo.png")
Resource resourceFile;

Обратите внимание, что файл mail-logo.png находится в каталоге src/main/resources .

Вернемся к методу sendHtmlMessage. Мы добавим resourceFile как встроенное вложение , чтобы иметь возможность ссылаться на него с помощью CID:

helper.addInline("attachment.png", resourceFile);

Наконец, на изображение нужно ссылаться как в электронных письмах Thymeleaf, так и в электронных письмах FreeMarker, используя нотацию CID :

<img src="cid:attachment.png" />

9. Заключение

В этой статье мы увидели, как отправлять электронные письма Thymeleaf и FreeMarker, включая богатый HTML-контент.

В заключение, большая часть работы связана с Spring; поэтому использование того или другого очень похоже для простой потребности, такой как отправка электронных писем .

Как всегда, полный исходный код примеров можно найти на GitHub .