かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot でメール送信する Web アプリケーションを作る ( その6 )( メール送信画面の作成 )

概要

Spring Boot でメール送信する Web アプリケーションを作る ( その5 )( Controller クラス、Thymeleaf テンプレートファイルの作成 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • メール送信画面の作成
    • 今回はメール送信機能を実装します。

ソフトウェア一覧

参考にしたサイト

  1. spring-boot-sample-velocity
    https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-velocity

  2. VelocityAutoConfiguration.java
    https://github.com/spring-projects/spring-boot/blob/1.2.x/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java

  3. Spring Boot Reference Guide - Appendix A. Common application properties
    http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

  4. どこよりも早い Spring Boot 1.2 解説 #渋谷
    http://www.slideshare.net/makingx/spring-boot12

    • Spring Boot 1.2 のメール送信機能が書かれている 36ページからの「Email送信サポート」を参照しました。

手順

1.0.x-sendmail ブランチの作成

  1. IntelliJ IDEA で 1.0.x-sendmail ブランチを作成します。

build.gradle の変更

  1. spring-boot-sample-velocity の pom.xml では <groupId>org.apache.velocity</groupId><artifactId>velocity</artifactId> が記述されていて spring-boot-starter-velocity は記述されていないのですが、spring-boot-starter-velocity を build.gradle に記述すればいろいろ自動設定されるのではないかと思いましたので、使うべきか否かを判断するために調査しました。

    • おそらく自動設定される内容が実装されていると思われる VelocityAutoConfiguration.java を見た感じでは、
      • spring.velocity.enabled = false を設定すれば、HTML のテンプレートファイル用の設定は反映されない ( velocityViewResolver Bean が生成されない )。
      • Velocity を使用するために必要な velocityEngine Bean が自動で設定される。
      • Velocity 用の設定は Spring Boot で用意されている Appendix A. Common application properties の "spring.velocity" のものが使用できる。
      • 上記の内容であれば spring-boot-starter-velocity を記述して使用した方が良さそうです。
    • 念のため compile("org.apache.velocity:velocity") だけでも使用できるのか確認するために簡単なサンプルを作成してみたところ、org.springframework.ui.velocity.VelocityEngineUtils が使用できませんでした。build.gradle に compile("org.apache.velocity:velocity") を書くだけでは Velocity は使用できないようです。
    • よって spring-boot-starter-velocity を記述することにします。
  2. build.gradle を リンク先の内容 に変更します。

  3. Gradle projects View の左上にある「Refresh all Gradle projects」アイコンをクリックして、変更した build.gradle の内容を反映します。

Velocity、Spring Boot のメール送信機能を使用するための設定

  1. Velocity は以下の設定をします。

    • application.properties に以下の項目を設定します。
      • spring.velocity.enabled = false
        • HTML のテンプレートファイルとしては使用しないので、false に設定します。
      • spring.velocity.charset = UTF-8
        • この設定項目はデフォルトで UTF-8 ですが、spring.velocity.charset の設定をプログラム内で使用したいので明示的に設定します。
    • application-develop.properties に以下の項目を設定します。
      • spring.velocity.cache = false
        • develop 環境では cache は無効にします。
  2. Spring Boot のメール送信機能は以下の設定をします。

    • application-develop.properties, application-product.properties, application-unittest.properties それぞれに以下の項目を設定します ( 今回設定するのは同じ値ですが、通常テストと本番環境で設定が変わる項目なので環境毎の設定ファイルの方に記述します ) 。
      • spring.mail.host = localhost
      • spring.mail.port = 25
  3. application.properties, application-develop.properties, application-product.properties, application-unittest.properties は リンク先の内容 になります。

Form クラスの作成

  1. src/main/java/ksbysample/webapp/email/web/mailsend の下に MailsendForm.java を作成します。作成後、リンク先の内容 に変更します。

  2. html ファイルに記述ミスがあったので修正します。src/main/resources/templates/mailsend の下の mailsend.html を リンク先のその1の内容 に変更します。

Thymeleaf テンプレートファイルの修正

  1. メール送信画面の「性別」「項目」「商品」に表示する選択肢を定義するファイルを作成します。src/main/resources の下に constant.yml を作成します。作成後、リンク先の内容 に変更します。

  2. constant.yml のデータを取得するためのクラスを作成します。src/main/java/ksbysample/webapp/email/config の下に Constant.java を作成します。作成後、リンク先の内容 に変更します。

  3. src/main/resources/templates/mailsend の下の mailsend.html を リンク先のその2の内容 に変更します。

Controller クラスの修正

  1. src/main/java/ksbysample/webapp/email/web の下の MailsendController.javaリンク先のその1の内容 に変更します。

一旦、動作確認

  1. まずはここまでの変更で画面が正常に表示されることを確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

  2. ブラウザを起動し http://localhost:8080/mailsend へアクセスします。画面が正常に表示されることを確認します。

    f:id:ksby:20150420234849p:plain

Velocity テンプレートファイルの作成

Velocity テンプレートファイルの配置場所は Appendix A. Common application properties に記載されている spring.velocity.resource-loader-path のデフォルト設定では classpath:/templates/ になっていますので、templates ディレクトリの下に作成します。

  1. src/main/resources/templates の下に mail/MAIL001 ディレクトリを作成します。

  2. src/main/resources/templates/mail/MAIL001 の下に MAIL001-body.vm を作成します。作成後、リンク先の内容 に変更します。

Velocity 用ユーティリティクラスの作成

org.springframework.ui.velocity.VelocityEngineUtils は少し使いにくいので、Web アプリケーション専用のユーティリティクラスを作成します。

  1. src/main/java/ksbysample/webapp/email の下に util パッケージを作成します。

  2. src/main/java/ksbysample/webapp/email/util の下に VelocityUtils.java を作成します。作成後、リンク先の内容 に変更します。

Stream API を使用できるよう設定する

次のクラスを作成しようとしたら、プロジェクトのデフォルトの設定では Stream API が使用できませんでした。。。 設定を変更します。

  1. メイン画面のメニューから「File」->「Project Structure...」を選択して「Project Structure」ダイアログを表示します。

  2. 画面左側のツリーから「Project Settings」-「Project」を選択し、画面右側で「Project language level」の設定を「6 - @Override in interfaces」→「8 - lambdas, type annotations etc.」へ変更して「OK」ボタンをクリックします。

    f:id:ksby:20150422005459p:plain

Spring Boot でメール送信する Web アプリケーションを作る ( その3 )( Project の作成 ) の方にも後で記述を追加しておきます。

メール生成クラスの作成

  1. src/main/java/ksbysample/webapp/email/web/mailsend の下に MAIL001MailBuilder.java を作成します。作成後、リンク先の内容 に変更します。

メール送信用 Service クラスの作成

  1. src/main/java/ksbysample/webapp/email の下に service パッケージを作成します。

  2. src/main/java/ksbysample/webapp/email/service の下に EmailService.java を作成します。作成後、リンク先の内容 に変更します。

メール送信処理の実装

  1. src/main/java/ksbysample/webapp/email/web/mailsend の下の MailsendController.javaリンク先のその2の内容 に変更します。

動作確認

  1. 動作確認します。Run View で Ctrl+F5 を押して Tomcat を再起動します。

  2. ブラウザを起動し http://localhost:8080/mailsend へアクセスします。以下の画像の値を入力後、「送信」ボタンをクリックします。

    f:id:ksby:20150422013057p:plain

  3. メールが送信され、smtp4dev の画面に表示されます。

    f:id:ksby:20150422013228p:plain

  4. smtp4dev の画面のリストに表示されているデータをダブルクリックすると Windows Live メールの画面が開き、送信されたメールの内容が表示されます。

    f:id:ksby:20150422013503p:plain

  5. Run View で Ctrl+F2 を押して Tomcat を停止します。

commit、Push、Pull Request、マージ

  1. commit します。commit 時に Code Analysis のダイアログが表示されますので、「Review」ボタンをクリックして以下の対応をします。

    • Unused property の Warning は無視します。
    • Attribute th:... is not allowed here の Warning が出ていましたので、出なくなるようにします。対象は th:object, th:field, th:each, th:value, th:text です。
  2. commit、GitHub へ Push、1.0.x-sendmail -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-sendmail ブランチを削除、をします。

課題&次回は。。。

  • 次回は Validation、その次にメール保存処理、最後にテストを実装します。
  • Thymeleaf テンプレートに設定ファイルの値を表示する方法が全然スマートじゃないですね。何か良い例はないものでしょうか。
  • クラスの設計 ( オブジェクト指向開発? ) がよく分かっていないなあと今回思いました。メール送信処理は Web や本等を見ながら作っては見たのですが、たぶんオブジェクト指向開発ならこういう風に作った方がよいみたいなものがあると思うんですよね。。。

ソースコード

build.gradle

dependencies {
    // spring-boot-gradle-plugin によりバージョン番号が自動で設定されるもの
    // Appendix E. Dependency versions ( http://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html ) 参照
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("org.springframework.boot:spring-boot-starter-velocity")
    compile("org.springframework.boot:spring-boot-starter-mail")
    compile("org.codehaus.janino:janino")
    testCompile("org.springframework.boot:spring-boot-starter-test")
    testCompile("org.yaml:snakeyaml")

    // spring-boot-gradle-plugin によりバージョン番号が自動で設定されないもの
    compile("org.postgresql:postgresql:9.4-1201-jdbc41")
    compile("org.seasar.doma:doma:2.2.0")
    compile("org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16")
    compile("org.apache.commons:commons-lang3:3.4")
    compile("org.projectlombok:lombok:1.16.2")
    testCompile("org.dbunit:dbunit:2.5.0")
}
  • compile("org.apache.velocity:velocity") を削除します。
  • compile("org.springframework.boot:spring-boot-starter-velocity") を追加します。
  • compile("org.springframework.boot:spring-boot-starter-mail") を追加します。

application.properties, application-develop.properties, application-product.properties, application-unittest.properties

■application.properties

hibernate.dialect = org.hibernate.dialect.PostgreSQL9Dialect

spring.jpa.hibernate.ddl-auto = none
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy

spring.velocity.enabled = false
spring.velocity.charset = UTF-8
  • spring.velocity.enabled, spring.velocity.charset を追加します。

■application-develop.properties

spring.datasource.url = jdbc:log4jdbc:postgresql://localhost/postgres
spring.datasource.username = postgres
spring.datasource.password = xxxxxxxx
spring.datasource.driverClassName = net.sf.log4jdbc.sql.jdbcapi.DriverSpy

spring.mail.host = localhost
spring.mail.port = 25

spring.messages.cache-seconds = 0

spring.thymeleaf.cache = false

spring.velocity.cache = false
  • spring.mail.host, spring.mail.port, spring.velocity.cache を追加します。

■application-product.properties

server.tomcat.basedir = C:/webapps/ksbysample-webapp-email

spring.datasource.url = jdbc:postgresql://localhost/postgres
spring.datasource.username = postgres
spring.datasource.password = xxxxxxxx
spring.datasource.driverClassName = org.postgresql.Driver

spring.mail.host = localhost
spring.mail.port = 25

spring.thymeleaf.cache = true
  • spring.mail.host, spring.mail.port を追加します。

■application-unittest.properties

spring.datasource.url = jdbc:postgresql://localhost/postgres
spring.datasource.username = postgres
spring.datasource.password = xxxxxxxx
spring.datasource.driverClassName = org.postgresql.Driver

spring.mail.host = localhost
spring.mail.port = 25

spring.thymeleaf.cache = true
  • spring.mail.host, spring.mail.port を追加します。

MailsendForm.java

package ksbysample.webapp.email.web.mailsend;

import lombok.Data;

import java.util.List;

@Data
public class MailsendForm {

    private String from;

    private String to;

    private String subject;

    private String name;

    private String sex;

    private String type;

    private List<String> item;

    private String naiyo;

}

mailsend.html

■その1

                                <div class="form-group">
                                    <label for="subject" class="control-label col-sm-2">Subject</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-12"><input type="text" name="subject" id="subject" class="form-control input-sm" value="" placeholder="件名を入力して下さい"/></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>
  • <label for="to" ...<label for="subject" ... に変更します。

■その2

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>ksbysample-webapp-email</title>
    <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'/>

    <meta th:replace="common/head-cssjs"/>
    <style>
    <!--
    .checkbox label,
    .radio label {
        padding-right: 10px;
    }
    -->
    </style>
</head>
<body class="skin-blue">
<div class="wrapper">

    <!-- Main Header -->
    <div th:replace="common/mainparts :: main-header"></div>

    <!-- Left side column. contains the logo and sidebar -->
    <div th:replace="common/mainparts :: main-sidebar (active='mailsend')"></div>

    <!-- Content Wrapper. Contains page content -->
    <div class="content-wrapper">
        <!-- Content Header (Page header) -->
        <section class="content-header">
            <h1>
                メール送信画面
            </h1>
        </section>

        <!-- Main content -->
        <section class="content">
            <div class="row">
                <div class="col-xs-12">
                    <form id="mailsendForm" method="post" action="/mailsend/send" th:action="@{/mailsend/send}" th:object="${mailsendForm}" class="form-horizontal">
                        <!--<div class="callout callout-danger">-->
                            <!--<p>共通エラーメッセージ表示エリア</p>-->
                        <!--</div>-->
                        <div class="box box-primary">
                            <div class="box-body">
                                <div class="form-group">
                                    <label for="from" class="control-label col-sm-2">From</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-8"><div class="input-group"><span class="input-group-addon"><i class="fa fa-envelope"></i></span><input type="text" name="from" id="from" class="form-control input-sm" value="" placeholder="Fromアドレスを入力して下さい" th:field="*{from}"/></div></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="to" class="control-label col-sm-2">To</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-8"><div class="input-group"><span class="input-group-addon"><i class="fa fa-envelope"></i></span><input type="text" name="to" id="to" class="form-control input-sm" value="" placeholder="Toアドレスを入力して下さい" th:field="*{to}"/></div></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="subject" class="control-label col-sm-2">Subject</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-12"><input type="text" name="subject" id="subject" class="form-control input-sm" value="" placeholder="件名を入力して下さい" th:field="*{subject}"/></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="name" class="control-label col-sm-2">氏名</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-8"><input type="text" name="name" id="name" class="form-control input-sm" value="" placeholder="(例) 田中 太郎" th:field="*{name}"/></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label class="control-label col-sm-2">性別</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-12">
                                            <div class="radio">
                                                <label th:each="sex : ${T(ksbysample.webapp.email.config.Constant).getInstance().SEX_MAP.entrySet()}">
                                                    <input type="radio" name="sex" th:value="${sex.getKey()}" th:text="${sex.getValue()}" th:field="*{sex}"/>
                                                </label>
                                            </div>
                                        </div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label class="control-label col-sm-2">項目</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-8">
                                            <select name="type" id="type" class="form-control input-sm" th:field="*{type}">
                                                <option th:each="type : ${T(ksbysample.webapp.email.config.Constant).getInstance().TYPE_MAP.entrySet()}"
                                                        th:value="${type.getKey()}"
                                                        th:text="${type.getValue()}">sex</option>
                                            </select>
                                        </div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label class="control-label col-sm-2">商品</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-12">
                                            <div class="checkbox">
                                                <label th:each="item : ${T(ksbysample.webapp.email.config.Constant).getInstance().ITEM_MAP.entrySet()}">
                                                    <input type="checkbox" name="item" th:value="${item.getKey()}" th:text="${item.getValue()}" th:field="*{item}"/>
                                                </label>
                                            </div>
                                        </div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="naiyo" class="control-label col-sm-2">内容</label>
                                    <div class="col-sm-10">
                                        <div class="row"><div class="col-sm-12"><textarea rows="5" name="naiyo" id="naiyo" class="form-control input-sm" placeholder="お問い合わせ内容を入力して下さい" th:field="*{naiyo}"></textarea></div></div>
                                        <!--<div class="row"><div class="col-sm-10"><p class="form-control-static text-danger"><small>ここにエラーメッセージを表示します</small></p></div></div>-->
                                    </div>
                                </div>
                            </div>
                            <div class="box-footer">
                                <div class="text-center">
                                    <button type="button" id="send" value="send" class="btn btn-primary">送信</button>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </section>
        <!-- /.content -->
    </div>
    <!-- /.content-wrapper -->

</div>
<!-- ./wrapper -->

<!-- REQUIRED JS SCRIPTS -->

<div th:replace="common/bottom-js"></div>
<script type="text/javascript">
<!--
$(document).ready(function() {
    $('#from').focus();

    $('#send').bind('click', function(){
        $('#mailsendForm').submit();
    });
});
-->
</script>
</body>
</html>
  • 以下の変更をします。
    • チェックボックスラジオボタンの右側のスペースを調整したいので、.checkbox label, .radio label { padding-right: 10px; } の定義を追加します。
    • form タグの id を mailsendForm に変更し、th:object="${mailsendForm}" を追加します。
    • 性別のラジオボタン、項目のドロップダウンリスト、商品のチェックボックスの値、名称を Constant クラスから取得して出力するよう変更します。
    • 各入力項目に th:field="*{...}" を追加します。
    • 最後に記述している Javascript で、$('#mailSendForm').submit();$('#mailsendForm').submit(); へ変更します。

constant.yml

!!ksbysample.webapp.email.config.Constant
SEX_MAP:
  1: 男性
  2: 女性
TYPE_MAP:
  1: 資料請求
  2: 商品に関する苦情
  3: その他
ITEM_MAP:
  101: 商品1
  102: 商品2
  103: 商品3

Constant.java

package ksbysample.webapp.email.config;

import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;

import java.util.Map;

@Component
public class Constant {

    private static final Constant instance = (Constant) new Yaml().load(Constant.class.getResourceAsStream("/constant.yml"));

    public static Constant getInstance() {
        return instance;
    }

    // 性別
    public Map<String, String> SEX_MAP;

    // 問い合わせ項目
    public Map<String, String> TYPE_MAP;

    // 商品
    public Map<String, String> ITEM_MAP;

}

MailsendController.java

■その1

    @RequestMapping
    public String index(MailsendForm mailsendForm
            , Model model) {
        return "mailsend/mailsend";
    }
  • index メソッドの引数に MailsendForm mailsendFormModel model を追加します。

■その2

package ksbysample.webapp.email.web.mailsend;

import ksbysample.webapp.email.service.EmailService;
import ksbysample.webapp.email.util.VelocityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/mailsend")
public class MailsendController {

    @Autowired
    private VelocityUtils velocityUtils;

    @Autowired
    private EmailService emailService;

    @RequestMapping
    public String index(MailsendForm mailsendForm
            , Model model) {
        return "mailsend/mailsend";
    }

    @RequestMapping("/send")
    public String send(MailsendForm mailsendForm
            , Model model) {
        // メールを送信する
        SimpleMailMessage mailMessage = MAIL001MailBuilder.build()
                .setForm(mailsendForm)
                .setVelocityUtils(velocityUtils)
                .setTemplateLocation("mail/MAIL001/MAIL001-body.vm")
                .create();
        emailService.sendSimpleMail(mailMessage);

        return "redirect:/mailsend";
    }

}
  • private VelocityUtils velocityUtils; を追加します。
  • private EmailService emailService; を追加します。
  • send メソッドを上記の内容に変更します。

MAIL001-body.vm

氏名 : $name
性別 : $sex
項目 : $type
商品 : $item
内容 :
$naiyo

VelocityUtils.java

package ksbysample.webapp.email.util;

import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.velocity.VelocityEngineUtils;

import java.util.Map;

public class VelocityUtils {

    @Autowired
    private VelocityEngine velocityEngine;

    @Value("${spring.velocity.charset}")
    private String charset;

    public String merge(String templateLocation, Map<String, Object> model) {
        return VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine, templateLocation, charset, model);
    }

}

MAIL001MailBuilder.java

package ksbysample.webapp.email.web.mailsend;

import ksbysample.webapp.email.config.Constant;
import ksbysample.webapp.email.util.VelocityUtils;
import org.springframework.mail.SimpleMailMessage;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class MAIL001MailBuilder {

    private MailsendForm mailsendForm;

    private VelocityUtils velocityUtils;

    private String templateLocation;

    public static MAIL001MailBuilder build() {
        return new MAIL001MailBuilder();
    }

    public MAIL001MailBuilder setForm(MailsendForm mailsendForm) {
        this.mailsendForm = mailsendForm;
        return this;
    }

    public MAIL001MailBuilder setVelocityUtils(VelocityUtils velocityUtils) {
        this.velocityUtils = velocityUtils;
        return this;
    }

    public MAIL001MailBuilder setTemplateLocation(String templateLocation) {
        this.templateLocation = templateLocation;
        return this;
    }

    public SimpleMailMessage create() {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(mailsendForm.getFrom());
        mailMessage.setTo(mailsendForm.getTo());
        mailMessage.setSubject(mailsendForm.getSubject());

        Constant constant = Constant.getInstance();
        Map<String, Object> model = new HashMap<>();
        model.put("name", mailsendForm.getName());
        model.put("sex", constant.SEX_MAP.get(mailsendForm.getSex()));
        model.put("type", constant.TYPE_MAP.get(mailsendForm.getType()));

        String itemList = mailsendForm.getItem().stream()
                .map(constant.ITEM_MAP::get)
                .collect(Collectors.joining(", "));
        model.put("item", itemList);

        model.put("naiyo", mailsendForm.getNaiyo());
        mailMessage.setText(velocityUtils.merge(this.templateLocation, model));

        return mailMessage;
    }

}

EmailService.java

package ksbysample.webapp.email.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

@Service
public class EmailService {

    @Autowired
    private MailSender mailSender;

    public void sendSimpleMail(SimpleMailMessage mailMessage) {
        mailSender.send(mailMessage);
    }

}

履歴

2015/04/22
初版発行。