RESTEasyとJPAとAngularJSを使ってWebアプリを作ってみる６（メール送信）

子供が実際にやったかどうかを確認するために、回答を保存した後で、メールの送信を行います。

本筋とは関係ないけど、いつも忘れてあちこち見て回ったりするので、忘備録として書いておきます。

# javamail
基本的に以下の手順でメールを送信します。

- Session#getInstance(Properties, Authenticator) でセッションを作成します。
- new MimeMessage(Session) でメッセージを生成します。
- MimeMessage#setSubject(String, String) でタイトルを設定します。第2引数の文字コードは ISO-2022-JP を指定します。
- MimeMessage#setText(String, String) で本文を設定します。第2引数はタイトルと一緒です。本文の改行には \r\n を使用します。
- MimeMessage#setRecipients(MimeMessage.RecipientType.TO, InternetAddress) であて先を指定します。
- MimeMessage#saveChanges() でメールを保存します。
- Transport#send(MimeMessage) でメールを送信します。

# GMailでの送信設定内容
GMailを利用してメール送信する場合は以下の設定をセッションを生成する際のプロパティに指定します。

```properties
mail.smtp.host = smtp.gmail.com
mail.smtp.port = 587
mail.smtp.auth = true
mail.smtp.starttls.enable = true
```

メール送信のログを出力したい場合は mail.debug = true もプロパティに指定します。

今回作ったメール送信クラスは以下の通りです。

```java:MailSender.java
package homework.utils;

import java.util.List;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.StringUtils;

import homework.entity.Answer;
import homework.entity.History;
import homework.entity.User;
import homework.utils.Constant.CorrectWrong;

/**
 * メール送信クラス。
 * @author satake
 */
public class MailSender implements Runnable {

	/** メール送信設定ファイル名 */
	private static final String CONFIG_NAME = "mail.properties";
	/** 送信用アカウントを設定ファイルから取得するキーの定義 */
	private static final String KEY_USERID = "account";
	/** 送信用パスワードを設定ファイルから取得するキーの定義 */
	private static final String KEY_PASSWD = "password";
	/** 送信先アドレスのセパレータの定義 */
	private static final String MAIL_SEPARATOR = "\\|@\\|";
	/** メール本文の改行文字の定義 */
	private static final String NEXT_LINE = "\r\n";
	/** メールの文字コードの定義 */
	private static final String CHAR_SET = "ISO-2022-JP";

	private final User user;
	private final History history;
	private final List<Answer> answers;

	/**
	 * コンストラクタ。
	 * @param user		ユーザ情報
	 * @param history	履歴情報
	 * @param answers	回答情報
	 */
	public MailSender(User user, History history, List<Answer> answers) {
		this.user = user;
		this.history = history;
		this.answers = answers;
	}

	@Override
	public void run() {
		send();
	}

	/**
	 * 実施結果をメール送信する。
	 */
	public void send() {
		try {
			// 設定読み込み
			Properties property = new Properties();
			property.load(getClass().getClassLoader().getResourceAsStream(CONFIG_NAME));

			// セッションの作成
			Session session = Session.getInstance(property, new Authenticator() {
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(property.getProperty(KEY_USERID), property.getProperty(KEY_PASSWD));
				}
			});

			// メールの作成
			MimeMessage mimeMessage = createMail(session);

			// 宛先の設定
			String[] noticeMails = user.getNoticeMail().split(MAIL_SEPARATOR);
			InternetAddress[] toAddress = new InternetAddress[noticeMails.length];
			for (int i = 0; i < noticeMails.length; i++) {
				toAddress[i] = new InternetAddress(noticeMails[i]);
			}
			mimeMessage.setRecipients(MimeMessage.RecipientType.TO, toAddress);

			// 送信者の設定
			InternetAddress fromAddress = new InternetAddress("noreply@system.com", "ホームワーク");
			mimeMessage.setFrom(fromAddress);

			// 保存
			mimeMessage.saveChanges();

			// 送信
			Transport.send(mimeMessage);
		}
		catch (Exception e) {
			throw new SystemException("メール送信に失敗しました。", e);
		}
	}

	/**
	 * メッセージを生成する。
	 * @param session	メールセッション
	 * @return	メッセージ
	 * @throws MessagingException	メッセージの設定に失敗した場合。
	 */
	private MimeMessage createMail(Session session) throws MessagingException {
		MimeMessage mimeMessage = new MimeMessage(session);

		// タイトル
		String title = "【ドリルの結果】（" + DateUtil.toString(DateUtil.getDate(), "yyyy/MM/dd") + "）" + user.getLastName() + user.getFirstName();
		mimeMessage.setSubject(title, CHAR_SET);

		// 本文
		StringBuilder text = new StringBuilder();
		text.append(user.getLastName()).append(user.getFirstName()).append("さんの実施結果").append(NEXT_LINE);
		text.append(NEXT_LINE);
		int elapsed = history.getElapsed() / 1000;
		text.append("所要時間： 約").append(elapsed / 60).append("分").append(elapsed % 60).append("秒").append(NEXT_LINE);
		text.append("正解率　： ").append(history.getCorrectPercent()).append("%").append(NEXT_LINE);
		text.append(NEXT_LINE);
		text.append("問題と解答は以下の通りです。").append(NEXT_LINE);
		text.append("-----------------------------------------------------").append(NEXT_LINE);
		int index = 1;
		for (Answer answer : answers) {
			text.append("問題").append(index).append(NEXT_LINE);
			text.append("　　").append(answer.getQuestion().getQuestion()).append(NEXT_LINE);
			text.append("回答　⇒　").append(answer.getCorrectWrong() == CorrectWrong.COLLECT ? "正解" : "不正解").append(NEXT_LINE);
			text.append("　　").append(StringUtils.isNotBlank(answer.getAnswer()) ? answer.getAnswer() : "未回答").append(NEXT_LINE);
			text.append("解答").append(NEXT_LINE);
			text.append("　　").append(answer.getQuestion().getCorrect()).append(NEXT_LINE);
			text.append("-----------------------------------------------------").append(NEXT_LINE);
			index++;
		}
		text.append(NEXT_LINE);
		text.append(NEXT_LINE);
		text.append("-----------------------------------------------------").append(NEXT_LINE);
		text.append("※ このメールはシステムより自動的に送信されています。").append(NEXT_LINE);
		text.append(NEXT_LINE);
		mimeMessage.setText(text.toString(), CHAR_SET);

		return mimeMessage;
	}
}
```
```properties:mail.properties
# Gmail 送信設定
mail.smtp.host = smtp.gmail.com
mail.smtp.port = 587
mail.smtp.auth = true
mail.smtp.starttls.enable = true
mail.debug = true

# 認証設定
account = 送信に使用するGMailアドレス
password = 送信に使用するGMailアドレスのパスワード
```

なお、メールの送信には時間がかかるので、別スレッドで処理させることにしました。

```java:UserService.java
	protected Responce registAnswer(Request request) {
		..........
		// メール送信
		if (StringUtils.isNotBlank(request.getUser().getNoticeMail())) {
			MailSender mailSender = new MailSender(request.getUser(), history, request.getAnswers());
			Executors.newSingleThreadExecutor().execute(mailSender);
		}
		..........
	}
```



[RESTEasyとJPAとAngularJSを使ってWebアプリを作ってみる７（サービスクラスの公開）](http://qiita.com/1roh/items/bf8435aade5b33be66d2)へ