メール機能を実装してみる
GAEで作成してみている「かんばんりすと」の内容をメールで自分の携帯に送ってみたくなった。どうしてWebアプリなのにわざわざこんなことがしたいのかというと、自分は携帯のパケット定額プランには入っていなくて(節約のため au の Eプラン)、リストをチェックするにもパケット料金が掛かって嫌だなぁと思い、テキストの軽いページを作って凌いでいたが、twitterにメールでアクセスできる「やぶみん」というサービスを使っていて「なんでもメールで送っちゃえば無料じゃん、これはいい!」、と思ったからである。
で、GoogleAppEngineのアプリ内からメールを送信する方法は既にいろんなところで書かれていたのでやってみた。特に新しい話題は無いので以下は完全に自分用のメモ。
仕様イメージ
実装
- jspの適当な位置に以下を記述。サブミットでsendMailAjax()メソッドにメアドを設定して呼ぶ。
<form method="post" onsubmit="sendMailAjax($('#mail_addr').get(0).value);return false;"> <input id="sendmail_button" type="submit" value="SendMail" style="font-size:12px" /> <input type="text" id="mail_addr" name="ttl" value="" size="40" style="font-weight:normal;padding:2px;background:#ffc"/></br> </form>
- javascript で Ajax を使ってイベント送信
function sendMailAjax(addr) { $('#info').html("Sending mail to " + addr + " ..."); $.ajax({ type: "POST", cache: false, url: "sendmail", data: "mail_addr=" + addr, success: function(response){ $('#info').html(response); } }); }
- Ajaxから飛んで来る sendmail に対応したコントローラ SendmailController を生成する
- とりあえずベタっと書いてみた
- try{} の中がメール送信のメイン部分。
- 送信元アドレスはアプリの開発者のメアドでないといけなかったため、別途 kanban.list@gmail.com のアカウントを新規で取得し、このアプリの開発者に追加した。(GAEアプリ設定画面の[Administration]->[Permissions]から登録)
- エラーがスローされなかった場合はメアドをクッキー登録している(setMailAddrToCookie)
- タスク表示のページでメアドのクッキーの内容を次回表示するようにする。(コードは省略)
- レスポンスは OK か NG かの文字列を Ajax のハンドラに投げる
- 複数の送信先を指定したい場合は msg.addRecipient() を何度も呼べば良い
package slim3.controller.todo; import org.slim3.controller.Controller; import org.slim3.controller.Navigation; import java.io.UnsupportedEncodingException; import java.util.Properties; import javax.mail.MessagingException; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.servlet.http.Cookie; import slim3.service.todo.TodoTaskService; public class SendmailController extends Controller { TodoTaskService service = new TodoTaskService(); @Override public Navigation run() throws Exception { String user = sessionScope("user"); String mail_addr = requestScope("mail_addr"); String title_text = user + " りすと"; // DataStoreからメール送信したいテキストを取得 String list_text = service.getSendMailText(user); //メールを送る try { Session session = Session.getDefaultInstance(new Properties(), null); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress("kanban.list@gmail.com", "かんばんりすと", "ISO-2022-JP")); msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mail_addr)); //送信先のメールアドレス msg.setSubject(title_text, "ISO-2022-JP"); msg.setText(list_text, "ISO-2022-JP"); Transport.send(msg); setMailAddrToCookie(mail_addr); response.getWriter().write("<font color=blue>SendMail OK! to " + mail_addr + "</font>"); } catch (UnsupportedEncodingException e) { response.getWriter().write("<font color=red>SendMail NG-EncordError! to " + mail_addr + "</font>"); } catch (MessagingException e) { response.getWriter().write("<font color=red>SendMail NG-MessageingError! to " + mail_addr + "</font>"); } return null; } protected void setMailAddrToCookie(String addr){ int cookie_age_sec = 60*60*24*30*12; // 12 month Cookie cookie = new Cookie("mail_addr",addr); cookie.setMaxAge(cookie_age_sec); cookie.setPath("/"); response.addCookie(cookie); } }
- 携帯で受け取るには当たり前だけどメールフィルターの設定で kanban.list@gmail.com を通るようにする。(しばらく気がつかずハマった)
- ローカルの環境だと上手く動いていたとしてもメールは飛んでこないみたい。デプロイして確認する。
- メール送信処理は別メソッドかサービスに分けたいけど、どういうI/Fにすればよいのか悩む。
- メール受信の方はまだ未着手。以下を参考にやってみる
- やっぱりメールで受け取れると凄く便利。家とかでタスクに登録して、出がけにメール送信しておいて後で見られる。自分が実際に使っている用途としては、日用品で足りないものをリストに日々 Waiting に登録しておき、買い物に行く際にメールで送信しておいて出先で見ながら買い物するという感じ(だから Waiting だけわかればいい)。今までは直にアプリにアクセスしていたらパケット代もったいなかったんだよなぁ。まさに自分用の節約機能。