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 .