Open Sourceで自宅Webアプリケーション -- Uprushの構築
蒋 いつ峰 2008/06/12   |  Java
Velocity でテンプレート メールを送信 2008/06/12  |  PK:Velocity メール テンプレート

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メソッドです。

 
  1. public String sendTemplate(String to, String subject, String vm, Map<String, Object> value) throws Exception{  
  2.     StringWriter sw = null;  
  3.     try {  
  4.         String propertyFile = _rb.getString("velocity.properties");  
  5.         Velocity.init(propertyFile);  
  6.           
  7.         VelocityContext context = new VelocityContext();  
  8.         for(String key : value.keySet()) {  
  9.             context.put(key, value.get(key));  
  10.         }  
  11.         Template template = null;  
  12.   
  13.         template = Velocity.getTemplate(vm);  
  14.   
  15.         sw = new StringWriter();  
  16.         template.merge( context, sw );  
  17.         sw.flush();  
  18.         String msg = sw.toString();  
  19.           
  20.         Collection<String> toList = new ArrayList<String>();  
  21.         toList.add(to);  
  22.         String from = _rb.getString("mail.from");  
  23.         String fromName = _rb.getString("mail.fromName");  
  24.           
  25.         return send(toList, nullnull, from, fromName, subject, msg);  
  26.     } finally {  
  27.         if (sw != null) {  
  28.             sw.close();  
  29.         }  
  30.     }  
  31.       
  32. }  

「_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 を指定するように修正した後のソースです。

 
  1. public Email setMsg(String msg) throws EmailException  
  2. {  
  3.     if (EmailUtils.isEmpty(msg))  
  4.     {  
  5.         throw new EmailException("Invalid message supplied");  
  6.     }  
  7.   
  8.     String useCharset = (charset == null ? TEXT_PLAIN : TEXT_PLAIN + "; charset=" + charset);  
  9.     setContent(msg, useCharset);  
  10.   
  11.     // setContent(msg, TEXT_PLAIN);  
  12.     return this;  
  13. }  


メール送信

最後はCommons Emailを呼び出して、メールを送信する。

 
  1. public String send(Collection<String> to, Collection<String> cc, Collection<String> bcc, String from,  
  2.         String fromName, String subject, String msg) throws Exception{  
  3.   
  4.     try {  
  5.         // host を取得  
  6.         String host = _rb.getString("mail.host");  
  7.         String charset = _rb.getString("mail.charset");  
  8.           
  9.         // メール設定  
  10.         SimpleEmail mail = new SimpleEmail();  
  11.         mail.setHostName(host);  
  12.         mail.setCharset(charset);  
  13.         for (String toAddr : to) {  
  14.             mail.addTo(toAddr);  
  15.         }  
  16.         if (cc != null) {  
  17.             for (String ccAddr : cc) {  
  18.                 mail.addCc(ccAddr);  
  19.             }  
  20.         }  
  21.         if (bcc != null) {  
  22.             for (String bccAddr : bcc) {  
  23.                 mail.addBcc(bccAddr);  
  24.             }  
  25.         }  
  26.         mail.setFrom(from, fromName);  
  27.           
  28.         mail.setSubject(subject);  
  29.           
  30.         mail.setMsg(msg);  
  31.         mail.setAuthentication(_rb.getString("mail.user"), _rb.getString("mail.password"));  
  32.           
  33.         return mail.send();  
  34.           
  35.     } catch (EmailException ee) {  
  36.           
  37.         // 宛先不明であるかどうか  
  38.            Throwable ex = ee.getCause();  
  39.   
  40.            do {  
  41.                if (ex instanceof SendFailedException) {  
  42.                    SendFailedException sfex = (SendFailedException) ex;  
  43.                    Address[] invalid = sfex.getInvalidAddresses();  
  44.   
  45.                    if (invalid != null) {  
  46.                     _isAddressError = true;  
  47.                    }  
  48.   
  49.                    Address[] validUnsent = sfex.getValidUnsentAddresses();  
  50.   
  51.                    if (validUnsent != null) {  
  52.                     _isAddressError = true;  
  53.                    }  
  54.   
  55.                    Address[] validSent = sfex.getValidSentAddresses();  
  56.   
  57.                    if (validSent != null) {  
  58.                     _isAddressError = true;  
  59.                    }  
  60.                }else if (ex instanceof MessagingException) {  
  61.                    ex = ((MessagingException) ex).getNextException();  
  62.                } else {  
  63.                    ex = null;  
  64.                }  
  65.            } while (ex != null);  
  66.            throw ee;  
  67.     }  
  68. }  

 


閲覧  |  コメント  |  目次

 
ヘルプ  |  ご利用規約  |  相互リンク  |  問合せ
リンクはご自由に、問合せはお気軽に
©2007 Uprush