Uprush はメール送信機能がある。例えば、登録時の確認メール、コンテンツにコメントが書かれた時、知らせて欲しい会員にメールを送る。これらのメール全体のフォーマットが決まっていて、その一部だけを動的に変更してメールすることになる。こういう場合、Apache Velocity を利用したほうが便利。
Velocity はJavaベースの汎用テンプレートエンジンです。Webページ生成、ソースコード・設定ファイルの自動生成など様々な用途で利用可能です。Uprush の場合は、コンテンツ編集画面がJSP以外、他のページは全てVelocityを使って生成されている。
メール本文
ここで、Velocity を使って、Uprush のコメントお知らせメールを生成する。生成するメールは下記の通りです。
将太郎 様
Uprush よりお知らせです。
投稿されたコンテンツ 「Open Sourceで自宅Webアプリケーション -- Uprushの構築」 にコメントが寄せられてきました。
以下の URL よりご確認してください。
確認 URL↓
http://uprush.net/pc/bk?aid=bkCmt&bookId=69
=====================================================================
■このメールをお送りしているアドレスは送信専用となっており、
返信していただいても回答いたしかねます。
■発行 Uprush
■ホームページ http://uprush.net/
■お問合せ webmaster@uprush.net
Copyright(C) Uprush. All rights reserved
===================================================================== |
テンプレート
上記メールのなか、会員名、コンテンツ名と確認URLは動的な内容です。このメールのテンプレート・ファイルは下記 mailComment.vm です。
$nickname 様
Uprush よりお知らせです。
投稿されたコンテンツ 「$bookName」 にコメントが寄せられてきました。
以下の URL よりご確認してください。
確認 URL↓
$url
=====================================================================
■このメールをお送りしているアドレスは送信専用となっており、
返信していただいても回答いたしかねます。
■発行 Uprush
■ホームページ http://uprush.net/
■お問合せ webmaster@uprush.net
Copyright(C) Uprush. All rights reserved
===================================================================== |
テンプレート・ファイルを読み込んで、テンプレート内の変数に値を入れ替えのJavaメソッドです。
- public String sendTemplate(String to, String subject, String vm, Map<String, Object> value) throws Exception{
- 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();
- }
- }
-
- }
public String sendTemplate(String to, String subject, String vm, Map<String, Object> value) throws Exception{ 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 toList = new ArrayList(); 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 の内容の抜粋。
resource.loader=file
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 を指定するように修正した後のソースです。
- public Email setMsg(String msg) throws EmailException
- {
- if (EmailUtils.isEmpty(msg))
- {
- throw new EmailException("Invalid message supplied");
- }
-
- String useCharset = (charset == null ? TEXT_PLAIN : TEXT_PLAIN + "; charset=" + charset);
- setContent(msg, useCharset);
-
-
- return this;
- }
public Email setMsg(String msg) throws EmailException { 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を呼び出して、メールを送信する。
- public String send(Collection<String> to, Collection<String> cc, Collection<String> bcc, String from,
- String fromName, String subject, String msg) throws Exception{
-
- try {
-
- 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;
- }
- }
public String send(Collection<String> to, Collection cc, Collection bcc, String from, 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; } }
public Email setMsg(String msg) throws EmailException { 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; }
|