Thymeleafをメールテンプレートとして使う

thymeleaf-mail-template

Spring Boot の標準テンプレートエンジンである thymeleaf をメール用のテンプレートエンジンとして利用するための方法

はじめに

ソフトバンクのARM買収報道にびっくりな今日この頃、皆様いかがお過ごしですか。

Spring Boot のテンプレートエンジンと言えば thymeleaf が筆頭に挙げられますが、これをメール用のテンプレートエンジンとして利用するための方法に関して書きます。

Webアプリケーションではなく、Spring Batch アプリケーションから利用する方法になります。

※ビルドツールとして Maven を利用する方向で説明します。
※STS (Spring Tool Suite) を利用して Spring Boot プロジェクトを作成している前提です。

環境

環境は以下。 

Spring Boot 1.3.6

実装方法

Maven ( pom.xml ) の設定

pom.xml を作成します ( 以下 )。
Spring Boot の batch, mail, thymeleaf を dependency 設定しています。

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>jp.co.agilegroup.mailtest</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-boot-mail-test</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.3.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-batch</artifactId>
		</dependency>
		<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>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

application.yml

設定ファイルを記述します。
application.properties を利用する場合、適宜変更して下さい。

# application.yml

spring:
  mail:
    default-encoding: UTF-8
    protocol: smtp
    host: mail.hogehoge.jp
    port: 25
#    username: xxxx@hogehoge.jp
#    password: xxxxxxx
    properties:
      mail:
        from: suda@hogehoge.jp

  thymeleaf:
    check-template-location: false

Spring Boot でメール送信 ( SMTP ) を行う場合、org.springframework.mail.javamail.JavaMailSender を利用しますが、以下設定を記載する事で JavaMailSender のプロパティを指定する事が可能です。メール送信に必要な基本的なプロパティを指定可能です。

プロパティ説明
spring.mail.default-encodingメールのエンコーディング
ISO-2022-JP等も設定可
spring.mail.protocolメールプロトコル
spring.mail.hostメールサーバのホスト名
spring.mail.portポート番号
spring.mail.usernameSMTP認証が必要な場合の認証ユーザ名
spring.mail.passwordSMTP認証が必要な場合のパスワード
spring.mail.jndi-nameアプリケーションサーバで設定したJavaMailリソースを利用 ( jndiで指定 ) する場合に利用する ( 多分 )
spring.mail.test-connectionテスト接続するか? ( true / false )

上記以外に、javaMail のプロパティも設定可能です。

プロパティ説明
spring.mail.properties.<javamailのプロパティ>javaMailのプロパティ。
上では mail.from ( return-path に設定される ) を設定している。
参考 : JavaMail API documentation

Javaクラス作成

MailSendService

メール送信のためのクラスを作成します。

package jp.co.agilegroup.mailtest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Scope("prototype")
@Service
public class MailSendService {

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.properties.mail.from}")
    private String fromAddress;
    
	public void sendMail(String person) {
    	try {
			SimpleMailMessage message = new SimpleMailMessage();
			message.setFrom(fromAddress);
			message.setTo("suda@hogehoge.jp");
			String subject = String.format("こんにちは");
			message.setSubject(subject);
			message.setText(getMailText(person));
			javaMailSender.send(message);
		} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

    private String getMailText(String person) {
    	SpringTemplateEngine templateEngine = new SpringTemplateEngine();
    	templateEngine.setTemplateResolver(emailTemplateResolver());
    	Context context = new Context();
    	context.setVariable("person", person);
    	String result = null;
    	try {
    		result = templateEngine.process("mailtemplate", context);
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	return result;
    }

	private ClassLoaderTemplateResolver emailTemplateResolver() {
		ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
		templateResolver.setTemplateMode("HTML5");
		templateResolver.setPrefix("mail/");
		templateResolver.setSuffix(".html");
		templateResolver.setCharacterEncoding("UTF-8");
		templateResolver.setCacheable(true);
		return templateResolver;
	}
}
sendMail メソッド

JavaMailSender, 及び, SimpleMailMessage を利用してメールを送信しています。
From の値には ( application.yml で ) spring.mail.properties.mail.from に設定した値を利用しています。

getMailText メソッド

Thymeleaf テンプレートを利用してメール本文を生成しています。
テンプレートに関しては後述。

emailTemplateResolver メソッド

メール用の thymeleaf テンプレートリゾルバを設定/取得しています。
thymeleaf で処理可能なのは html/xml 系でプレーンテキストは扱えないため、Mode="HTML5" で指定。テンプレートの場所をPrefixで指定しています。

参考 : Thymeleafはどんな種類のテンプレートを処理できるの?

SpringBootMailTestApplication

Spring Boot (Batch) のメインクラスを作成します。
( MailSendService の sendMail を呼び出しているだけです )

package jp.co.agilegroup.mailtest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class SpringBootMailTestApplication implements CommandLineRunner {

	@Autowired
	private MailSendService mailSendService;
	
	public static void main(String[] args) {
        SpringApplication application = new SpringApplication(SpringBootMailTestApplication.class);
        application.setWebEnvironment(false);
        ApplicationContext context = application.run(args);
        SpringApplication.exit(context);
	}

	@Override
	public void run(String... as) throws Exception {
		String person = "World";
		if (as.length >= 1) {
			person = as[0];
		}
		mailSendService.sendMail(person);
	}
}

メールテンプレート

Thymeleaf のテンプレートを作成します。
リソースフォルダ下に /resources/mail/mailtemplate.html というファイル名で作成します。

今回はプレーンテキスト形式でメール送信するものとします。

<html th:inline="text" th:remove="tag">
Hello [[${person}]]
</html>

上述の通りThymeleaf では html, xml 系のテンプレートしか扱えないため、html 形式のテンプレートとなっています。
ポイントは以下。

  • th:inline="text" を指定し、html タグ内部のインラインテキストに含まれる変数を展開 ( 処理 ) するように設定。
  • th:remove="tag" を指定し、展開後には html タグを削除するように設定。
  • 変数は [[...]] で囲む。

まとめ

上記ファイル群を作成/実行してメールテンプレートが機能する事を確認できました。

その他

上記以外に確認した事など

  • 通常のWeb(HTML)用テンプレートと併用可能。
    記事ではバッチアプリケーションとしての例ですが、Webアプリケーションからも利用可能です。
    確認していないがConfiguration クラスで設定する事も可能かと思われる。
  • default-encoding は UTF-8、及び、ISO-2022-JP で動作確認。
  • SMTP認証は username, password 設定を行う事で対応できた。(但し暗号化無しの場合)
  • TLS認証絡みは未確認。
    javaMail のプロパティ mail.smtp.auth=true, mail.smtp.starttls=true 辺りを設定する事で対応可能かと思われる。