Velocityでメール送信
メール全体のフォーマットが決まっていて、その一部だけを動的に変更してメールを送信する場合、Apache Velocity を利用したほうが便利。
Velocity はJavaベースの汎用テンプレートエンジンです。Webページ生成、ソースコード・設定ファイルの自動生成など様々な用途で利用可能です。Uprush の場合は、コンテンツ編集画面がJSP以外、他のページは全てVelocityを使って生成されている。
- メール本文
ここで、Velocity を使って、Uprush のコメントお知らせメールを生成する。生成するメールは下記の通りです。
Uprush よりお知らせです。
投稿されたコンテンツ 「Velocityでメール送信」 にコメントが寄せられてきました。
以下の URL よりご確認してください。
確認 URL↓
http://uprush.net/node/33
=====================================================================
■このメールをお送りしているアドレスは送信専用となっており、
返信していただいても回答いたしかねます。
■発行 Uprush
■ホームページ http://uprush.net/
■お問合せ webmaster@uprush.net
Copyright(C) Uprush. All rights reserved
=====================================================================
- テンプレート
上記メールのなか、会員名、コンテンツ名と確認URLは動的な内容です。このメールのテンプレート・ファイルは下記 mailComment.vm です。
Uprush よりお知らせです。
投稿されたコンテンツ 「$bookName」 にコメントが寄せられてきました。
以下の URL よりご確認してください。
確認 URL↓
$url
=====================================================================
■このメールをお送りしているアドレスは送信専用となっており、
返信していただいても回答いたしかねます。
■発行 Uprush
■ホームページ http://uprush.net/
■お問合せ webmaster@uprush.net
Copyright(C) Uprush. All rights reserved
=====================================================================
テンプレート・ファイルを読み込んで、テンプレート内の変数に値を入れ替えのJavaメソッドです。
StringWriter sw = null;
try {
String propertyFile = _rb.getString("velocity.properties");
Velocity.init(propertyFile);
VelocityContext context = new VelocityContext();
for(String key : value.keySet()) {
context.put(key, value.get(key));
}
Template template = null;
template = Velocity.getTemplate(vm);
sw = new StringWriter();
template.merge( context, sw );
sw.flush();
String msg = sw.toString();
Collection<String> toList = new ArrayList<String>();
toList.add(to);
String from = _rb.getString("mail.from");
String fromName = _rb.getString("mail.fromName");
return send(toList, null, null, from, fromName, subject, msg);
} finally {
if (sw != null) {
sw.close();
}
}
}
「_rb.getString("velocity.properties")」はVelocityの設定ファイルを取得する、例えば 「src/resource/velocity.properties」です。velocity.properties には、テンプレートの文字コードとテンプレートファイルを配置するディレクトリのパスを設定している。
velocity.properties の内容の抜粋。
file.resource.loader.description = Velocity File Resource Loader
file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
file.resource.loader.path = /home/uprush/workspace/uprush/vm
input.encoding=UTF-8
output.encoding=UTF-8
default.contentType=text/html;charset=UTF-8
- Apache Commons Email の利用
メール送信はApache Commons Emailを 利用する。僕は使っているCommons Emailのバージョンが古いかもしれないが、日本語メールを送信する際に、本文が文字化けしてしまった。Commons Emailを直接使ってはいけないそうです(すでにバグ報告済みらしい)。Commons EmailはAPL2ライセンスでソースを公開しているので、この文字化けの問題は org.apache.commons.mail.SimpleEmail のソースを修正し再コンパイルで解決できる。
org.apache.commons.mail.SimpleEmail のsetMsgメソッドを、メール本文の charset を指定するように修正した後のソースです。
{
if (EmailUtils.isEmpty(msg))
{
throw new EmailException("Invalid message supplied");
}
String useCharset = (charset == null ? TEXT_PLAIN : TEXT_PLAIN + "; charset=" + charset);
setContent(msg, useCharset);
// setContent(msg, TEXT_PLAIN);
return this;
}
- メール送信
最後はCommons Emailを呼び出して、メールを送信する。
String fromName, String subject, String msg) throws Exception{
try {
// host を取得
String host = _rb.getString("mail.host");
String charset = _rb.getString("mail.charset");
// メール設定
SimpleEmail mail = new SimpleEmail();
mail.setHostName(host);
mail.setCharset(charset);
for (String toAddr : to) {
mail.addTo(toAddr);
}
if (cc != null) {
for (String ccAddr : cc) {
mail.addCc(ccAddr);
}
}
if (bcc != null) {
for (String bccAddr : bcc) {
mail.addBcc(bccAddr);
}
}
mail.setFrom(from, fromName);
mail.setSubject(subject);
mail.setMsg(msg);
mail.setAuthentication(_rb.getString("mail.user"), _rb.getString("mail.password"));
return mail.send();
} catch (EmailException ee) {
// 宛先不明であるかどうか
Throwable ex = ee.getCause();
do {
if (ex instanceof SendFailedException) {
SendFailedException sfex = (SendFailedException) ex;
Address[] invalid = sfex.getInvalidAddresses();
if (invalid != null) {
_isAddressError = true;
}
Address[] validUnsent = sfex.getValidUnsentAddresses();
if (validUnsent != null) {
_isAddressError = true;
}
Address[] validSent = sfex.getValidSentAddresses();
if (validSent != null) {
_isAddressError = true;
}
}else if (ex instanceof MessagingException) {
ex = ((MessagingException) ex).getNextException();
} else {
ex = null;
}
} while (ex != null);
throw ee;
}
}





