読者です 読者をやめる 読者になる 読者になる

かんがるーさんの日記

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

Spring Boot でメール送信する Web アプリケーションを作る ( その16 )( 日本語のファイル名の添付ファイル付メールを送信する )

概要

Spring Boot でメール送信する Web アプリケーションを作る ( その15 )( Thymeleaf を利用して HTML メールを送信する2 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 日本語のファイル名の添付ファイル付メールを送信する機能を実装します。
  • 以下の仕様で実装します。
    • メール送信画面に「ファイルを添付する」チェックボックスを追加します。チェックして「送信」ボタンがクリックされたら、application.properties に設定されたファイルを添付してメールを送信します。
    • application.properties の設定項目は mailsend.attached.file にします。
    • mailsend.attached.file は共通定義用の application.properties には記述せず、application-develop.properties, application-product.properties, application-unittest.properties に記述します。
    • mailsend.attached.file に日本語のファイル名のファイルが設定されていても送信できるようにします。
    • 「HTMLメール送信」ボタンは対応しません。

ソフトウェア一覧

参考にしたサイト

手順

ブランチの作成

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

application-develop.properties, application-product.properties, application-unittest.properties への設定項目の追加

  1. 添付ファイル用の日本語ファイル名のファイルを作成します。C:\project-springboot の下に テスト用ファイル001.txt を新規作成します。

  2. src/main/resources の下の application-develop.properties, application-product.properties, application-unittest.properties を リンク先の内容 に変更します。

mailsend.html の変更

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

    画面を変更している時に気づきましたが、spring.thymeleaf.cache = false を指定していても、bootRun で起動している場合は Thymeleaf のテンプレートファイルを修正しただけですぐに反映されますが、JRebel で起動している場合には Ctrl+F9 を押して make しないと反映されませんでした。

MailsendForm クラスの変更

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

  2. 画面を確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

  3. ブラウザを起動し http://localhost:8080/mailsend へアクセスします。「ファイルを添付する」チェックボックスが追加された以下の画面が表示されます。

    f:id:ksby:20150603062130p:plain

  4. Ctrl+F2 を押して Tomcat を停止します。

MAIL001MailHelper クラスの変更

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

  2. テストで使用する MailsendForm クラスのテストデータを作成します。src/test/resources/ksbysample/webapp/email/web/mailsend の下に mailsendForm_attached.yml を新規作成します。作成後、リンク先の内容 に変更します。

  3. テストを作成します。src/test/java/ksbysample/webapp/email/helper/mail の下の MAIL001MailHelperTest.javaリンク先の内容 に変更します。

  4. テストを実行します。MAIL001MailHelperTest クラス内の「添付ファイル付テキストメール生成のテスト」クラスの「MailsendFormの全てに値がセットされている場合」メソッドにカーソルを移動した後、コンテキストメニューを表示して「Run 'MailsendFormの全てに値が...()' with Coverage」メニューを選択します。

    テストが全て成功することを確認します。

    f:id:ksby:20150604005947p:plain

MailsendService クラスの変更

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

  2. テストを作成します。src/test/java/ksbysample/webapp/email/web/mailsend の下の MailsendServiceTest.javaリンク先の内容 に変更します。

  3. テストを実行します。MailsendServiceTest クラス内の「mailsendFormAttachedで添付ファイル付テキストメールを送信する場合」メソッドにカーソルを移動した後、コンテキストメニューを表示して「Run 'mailsendFormAttach...()' with Coverage」メニューを選択します。

    テストが全て成功することを確認します。

    f:id:ksby:20150605012528p:plain

動作確認

  1. メールサーバ smtp4dev を起動します。

  2. Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

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

    f:id:ksby:20150605014952p:plain

    smtp4dev に HTML メールが送信されますので、Windows Live メールで表示してみます。日本語のファイル名で文字化けせずに添付されており、ダブルクリックして開くとファイルも問題なく表示されました。

    f:id:ksby:20150605015656p:plain

  4. Run View で Ctrl+F2 を押して Tomcat を停止します。smtp4dev も終了します。

  5. Gradle projects View から build タスクを実行し、"BUILD SUCCESSFUL" が出力されることを確認します。

commit、Push、Pull Request、マージ

  1. commit します。commit 時に Code analysis failed ダイアログが表示されますが、「Commit」ボタンがデフォルトになっていましたので、そのままクリックします。

  2. GitHub へ Push、1.0.x-send-attachedmail -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-send-attachedmail ブランチを削除、をします。

ソースコード

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

■application-develop.properties

spring.datasource.url = jdbc:log4jdbc:postgresql://localhost/ksbyemail
spring.datasource.username = ksbyemail_user
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

mailsend.attached.file = C:/project-springboot/テスト用ファイル001.txt
  • mailsend.attatched.file を追加します。

■application-product.properties

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

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

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

spring.thymeleaf.cache = true

mailsend.attached.file = C:/project-springboot/テスト用ファイル001.txt
  • mailsend.attatched.file を追加します。

■application-unittest.properties

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

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

spring.thymeleaf.cache = true

mailsend.attached.file = C:/project-springboot/テスト用ファイル001.txt
  • mailsend.attatched.file を追加します。

mailsend.html

<!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;
    }
    .form-control-static {
        padding-top: 0px;
        padding-bottom: 0px;
    }
    .has-error .form-control {
        background-color: #fff5ee;
    }
    -->
    </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" th:if="${#fields.hasGlobalErrors()}">
                            <p th:each="err : ${#fields.globalErrors()}" th:text="${err}">共通エラーメッセージ表示エリア</p>
                        </div>

                        <div class="box box-primary">
                            <div class="box-body">
                                <div class="form-group" th:classappend="${#fields.hasErrors('*{fromAddr}')} ? 'has-error' : ''">
                                    <label for="fromAddr" 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="fromAddr" id="fromAddr" class="form-control input-sm" value="" placeholder="Fromアドレスを入力して下さい" th:field="*{fromAddr}"/></div></div></div>
                                        <div class="row" th:if="${#fields.hasErrors('*{fromAddr}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{fromAddr}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{toAddr}')} ? 'has-error' : ''">
                                    <label for="toAddr" 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="toAddr" id="toAddr" class="form-control input-sm" value="" placeholder="Toアドレスを入力して下さい" th:field="*{toAddr}"/></div></div></div>
                                        <div class="row" th:if="${#fields.hasErrors('*{toAddr}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{toAddr}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{subject}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{subject}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{subject}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{name}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{name}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{name}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{sex}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{sex}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{sex}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{type}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{type}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{type}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{item}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{item}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{item}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{naiyo}')} ? 'has-error' : ''">
                                    <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" th:if="${#fields.hasErrors('*{naiyo}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{naiyo}">ここにエラーメッセージを表示します</small></p></div></div>
                                    </div>
                                </div>

                                <div class="form-group" th:classappend="${#fields.hasErrors('*{attachedFile}')} ? 'has-error' : ''">
                                    <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>
                                                    <input type="checkbox" name="attachedFile" th:value="1" th:text="ファイルを添付する" th:field="*{attachedFile}"/>
                                                </label>
                                            </div>
                                        </div></div>
                                        <div class="row" th:if="${#fields.hasErrors('*{item}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{item}">ここにエラーメッセージを表示します</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>
                                    <button type="button" id="sendhtml" value="sendhtml" class="btn btn-default">HTMLメール送信</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() {
    $('#fromAddr').focus();

    $('#send').bind('click', function(){
        $('#mailsendForm').submit();
    });

    $('#sendhtml').bind('click', function(){
        $('#mailsendForm').attr('action', '/mailsend/sendhtml');
        $('#mailsendForm').submit();
    });
});
-->
</script>
</body>
</html>
  • 「内容」の項目の下に <div class="form-group" th:classappend="${#fields.hasErrors('*{attachedFile}')} ? 'has-error' : ''"> ... </div> を追加します。

MailsendForm.java

package ksbysample.webapp.email.web.mailsend;

import lombok.Data;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.Collections;
import java.util.List;

@Data
public class MailsendForm {

    @NotBlank
    @Email
    private String fromAddr;

    @NotBlank
    @Email
    private String toAddr;

    @NotBlank
    @Size(max = 128, message = "{error.size.max}")
    private String subject;

    @Size(max = 32, message = "{error.size.max}")
    private String name;

    @Pattern(regexp = "^(|1|2)$", message = "{mailsendForm.sex.pattern}")
    private String sex;

    @Pattern(regexp = "^(|1|2|3)$", message = "{mailsendForm.type.pattern}")
    private String type;

    private List<String> item;

    @Size(max = 2000, message = "{error.size.max}")
    private String naiyo;
    
    private String attachedFile;

}
  • private String attachedFile; を追加します。

MAIL001MailHelper.java

package ksbysample.webapp.email.helper.mail;

import ksbysample.webapp.email.config.Constant;
import ksbysample.webapp.email.util.VelocityUtils;
import ksbysample.webapp.email.web.mailsend.MailsendForm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class MAIL001MailHelper {

    private final String TEMPLATE_LOCATION_TEXTMAIL = "mail/MAIL001/MAIL001-body.vm";
    // templateEngine.processに渡すThymeleafのテンプレートファイルは拡張子.html付けないこと
    private final String TEMPLATE_LOCATION_HTMLMAIL = "mail/MAIL001/MAIL001-HTML-body";

    @Autowired
    private VelocityUtils velocityUtils;

    @Autowired
    private JavaMailSender mailSender;
    
    @Autowired
    private SpringTemplateEngine templateEngine;

    @Value("${mailsend.attached.file}")
    private String attachedFilePropertyValue;
    
    public SimpleMailMessage createMessage(MailsendForm mailsendForm) {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(mailsendForm.getFromAddr());
        mailMessage.setTo(mailsendForm.getToAddr());
        mailMessage.setSubject(mailsendForm.getSubject());
        mailMessage.setText(generateTextUsingVelocity(mailsendForm));
        return mailMessage;
    }

    public MimeMessage createHtmlMessage(MailsendForm mailsendForm) throws MessagingException {
        MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, false, "UTF-8");
        message.setFrom(mailsendForm.getFromAddr());
        message.setTo(mailsendForm.getToAddr());
        message.setSubject(mailsendForm.getSubject());
        message.setText(generateTextUsingThymeleaf(mailsendForm), true);
        return message.getMimeMessage();
    }

    public MimeMessage createAttachedMessage(MailsendForm mailsendForm) throws MessagingException {
        MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
        message.setFrom(mailsendForm.getFromAddr());
        message.setTo(mailsendForm.getToAddr());
        message.setSubject(mailsendForm.getSubject());
        message.setText(generateTextUsingVelocity(mailsendForm), false);

        // ファイルを添付する
        if (StringUtils.isNotEmpty(this.attachedFilePropertyValue)) {
            File file = new File(this.attachedFilePropertyValue);
            if (file.exists()) {
                String fileName = file.getName();
                message.addAttachment(fileName, file);
            }
        }
        
        return message.getMimeMessage();
    }
    
    private String generateTextUsingVelocity(MailsendForm mailsendForm) {
        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 = null;
        if (mailsendForm.getItem() != null) {
            itemList = mailsendForm.getItem().stream()
                    .map(constant.ITEM_MAP::get)
                    .collect(Collectors.joining(", "));
        }
        model.put("item", itemList);

        model.put("naiyo", mailsendForm.getNaiyo());
        return velocityUtils.merge(this.TEMPLATE_LOCATION_TEXTMAIL, model);
    }

    private String generateTextUsingThymeleaf(MailsendForm mailsendForm) {
        Constant constant = Constant.getInstance();
        Context ctx = new Context(LocaleContextHolder.getLocale());
        ctx.setVariable("name", mailsendForm.getName());
        ctx.setVariable("sex", constant.SEX_MAP.get(mailsendForm.getSex()));
        ctx.setVariable("type", constant.TYPE_MAP.get(mailsendForm.getType()));

        String itemList = null;
        if (mailsendForm.getItem() != null) {
            itemList = mailsendForm.getItem().stream()
                    .map(constant.ITEM_MAP::get)
                    .collect(Collectors.joining(", "));
        }
        ctx.setVariable("item", itemList);

        ctx.setVariable("naiyo", mailsendForm.getNaiyo());
        
        return this.templateEngine.process(this.TEMPLATE_LOCATION_HTMLMAIL, ctx);
    }
    
}

mailsendForm_attached.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: test@sample.com
toAddr: xxx@yyy.zzz
subject: テスト
name: 田中 太郎
sex: 1
type: 1
item:
  - 101
  - 102
  - 103
naiyo: これはテストです。
attachedFile: 1

MAIL001MailHelperTest.java

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 添付ファイル付テキストメール生成のテスト {

        private final MailsendForm mailsendFormAttach
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("/ksbysample/webapp/email/web/mailsend/mailsendForm_attach.yml"));

        @Autowired
        private MAIL001MailHelper mail001MailHelper;

        @Value("${mailsend.attached.file}")
        private String attachedFilePropertyValue;

        @Test
        public void MailsendFormの全てに値がセットされている場合() throws Exception {
            MimeMessage mimeMessage = mail001MailHelper.createAttachedMessage(mailsendFormAttach);
            assertThat(mimeMessage.getContent(), instanceOf(MimeMultipart.class));
            
            MimeMultipart mimeMultipart = (MimeMultipart) mimeMessage.getContent();
            assertThat(mimeMultipart.getCount(), is(2));

            MimeBodyPart bodyPart = (MimeBodyPart) mimeMultipart.getBodyPart(1);
            File file = new File(this.attachedFilePropertyValue);
            assertThat(MimeUtility.decodeText(bodyPart.getFileName()), is(file.getName()));
        }

    }
  • ネストクラス public static class 添付ファイル付テキストメール生成のテスト { ... } を追加します。

MailsendService.java

package ksbysample.webapp.email.web.mailsend;

import ksbysample.webapp.email.dao.EmailDao;
import ksbysample.webapp.email.dao.EmailItemDao;
import ksbysample.webapp.email.entity.Email;
import ksbysample.webapp.email.entity.EmailItem;
import ksbysample.webapp.email.helper.mail.MAIL001MailHelper;
import ksbysample.webapp.email.service.EmailService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

@Service
public class MailsendService {

    @Autowired
    private EmailDao emailDao;

    @Autowired
    private EmailItemDao emailItemDao;

    @Autowired
    private MAIL001MailHelper mail001MailHelper;

    @Autowired
    private EmailService emailService;

    public void saveAndSendEmail(MailsendForm mailsendForm) throws MessagingException {
        // 入力されたデータを email, email_item テーブルに保存する
        saveEmail(mailsendForm);

        // メールを送信する
        if (StringUtils.equals(mailsendForm.getAttachedFile(), "1")) {
            sendAttachedEmail(mailsendForm);
        }
        else {
            sendEmail(mailsendForm);
        }
    }

    public void saveAndSendHtmlEmail(MailsendForm mailsendForm) throws MessagingException {
        // 入力されたデータを email, email_item テーブルに保存する
        saveEmail(mailsendForm);

        // HTMLメールを送信する
        sendHtmlEmail(mailsendForm);
    }

    private void saveEmail(MailsendForm mailsendForm) {
        // email テーブルに保存する
        Email email = new Email();
        BeanUtils.copyProperties(mailsendForm, email);
        emailDao.insert(email);

        // email_item テーブルに保存する
        EmailItem emailItem = new EmailItem();
        if (mailsendForm.getItem() != null) {
            for (String item : mailsendForm.getItem()) {
                emailItem.setEmailItemId(null);
                emailItem.setEmailId(email.getEmailId());
                emailItem.setItem(item);
                emailItemDao.insert(emailItem);
            }
        }
    }

    private void sendEmail(MailsendForm mailsendForm) {
        SimpleMailMessage message = mail001MailHelper.createMessage(mailsendForm);
        emailService.sendSimpleMail(message);
    }

    private void sendHtmlEmail(MailsendForm mailsendForm) throws MessagingException {
        MimeMessage message = mail001MailHelper.createHtmlMessage(mailsendForm);
        emailService.sendMail(message);
    }
    
    private void sendAttachedEmail(MailsendForm mailsendForm) throws MessagingException {
        MimeMessage message = mail001MailHelper.createAttachedMessage(mailsendForm);
        emailService.sendMail(message);
    }

}
  • saveAndSendEmail メソッド内で mailsendForm.getAttachedFile() の値により呼び出すメール送信処理を変えるように変更します。
  • sendAttachedEmail メソッドを追加します。

MailsendServiceTest.java

    @Test
    public void mailsendFormAttachedで添付ファイル付テキストメールを送信する場合() throws Exception {
        mailsendService.saveAndSendEmail(mailsendFormAttached);

        // email, email_item テーブルに保存されているか確認する
        IDataSet dataSet = new CsvDataSet(new File("src/test/resources/ksbysample/webapp/email/web/mailsend/testdata/simple"));
        TableDataAssert tableDataAssert = new TableDataAssert(dataSet, dataSource);
        tableDataAssert.assertEquals("email", new String[]{"email_id"});
        tableDataAssert.assertEquals("email_item", new String[]{"email_item_id", "email_id"});

        // メールが送信されているか確認する
        assertThat(mailServer.getMessagesCount(), is(1));
        MimeMessage receiveMessage = mailServer.getFirstMessage();
        assertThat(receiveMessage.getFrom()[0], is(new InternetAddress("test@sample.com")));
        assertThat(receiveMessage.getAllRecipients()[0], is(new InternetAddress("xxx@yyy.zzz")));
        assertThat(receiveMessage.getSubject(), is("テスト"));

        assertThat(receiveMessage.getContent(), instanceOf(MimeMultipart.class));
        MimeMultipart mimeMultipart = (MimeMultipart) receiveMessage.getContent();
        assertThat(mimeMultipart.getCount(), is(2));

        // テキストメールの確認
        String mailsendFormSimpleMail
                = Files.toString(new File(getClass().getResource("mailsendForm_simple_mail.txt").toURI()), StandardCharsets.UTF_8);
        MimeBodyPart bodyPart = (MimeBodyPart) mimeMultipart.getBodyPart(0);
        MimeMultipart part = (MimeMultipart) bodyPart.getContent();
        String text = null;
        try (Reader reader = new InputStreamReader(part.getBodyPart(0).getInputStream())) {
            text = CharStreams.toString(reader);
        }
        assertThat(text, is(mailsendFormSimpleMail));

        // 添付ファイルの確認
        bodyPart = (MimeBodyPart) mimeMultipart.getBodyPart(1);
        File file = new File(this.attachedFilePropertyValue);
        assertThat(MimeUtility.decodeText(bodyPart.getFileName()), is(file.getName()));
    }
  • 「mailsendFormAttachedで添付ファイル付テキストメールを送信する場合」メソッドを追加します。

履歴

2015/06/05
初版発行。