※この記事は「heroku上でPlayframework2のwelcomeページを表示させることはできた」という前提で進めます
herokuからメールを送る
まず、そもそもherokuからどうやってメールを送るの?というところから。
手段としては、外部にSMTPサーバを用意するってのが一番単純で、ググると「herokuからGMailのSMTP叩く」みたいなのは出てきます。出てくるんですが、これやるにはそのSMTPの認証情報を直書きしてpushしなきゃいけないので、「できるんだけど扱いにくいなぁ」という印象でした。うまくやる方法あるのかな?あったら教えて下さい。
で、今回はherokuアドオンに頼ることにします。
https://addons.heroku.com/sendgrid
SendGridというアドオンがあったので使ってみることにしました。
1日200通まで無料の「Starter」プランで送れるそうです。どんなメールを送るかによりますが、とりあえず試すには十分すぎるのでこれを使います。
コマンドでもWebからでもいいので、SendGrid Starterをサクっとアプリケーションに追加しちゃってください。
このSendGridというアドオンはどのような仕組みでメールを送っているかというと、
- SMTPサーバ自体は外部にある
- 認証情報をアドオンから環境変数に渡してくれる
- あとはSMTP叩くだけ
という至極シンプルなものです。
これだけ書けばどうやってメール送るかは想像できるかもしれませんが、一応ひと通り書いていきます。
認証情報をPlayアプリケーションに渡す
herokuでPlayframework2ベースアプリケーションを動かすにはProcfileってのを作ったと思うので、これを編集して、環境変数をJavaシステムプロパティとしてアプリケーションに引渡します。DBを使わないメールのみ送れる一番単純なアプリだとこんな感じ。
web: target/start -Dhttp.port=${PORT} ${JAVA_OPTS} -Dmail.smtp.host=smtp.sendgrid.net -Dmail.smtp.port=587 -Dmail.smtp.auth=true -Dmail.smtp.user=${SENDGRID_USERNAME} -Dmail.smtp.pass=${SENDGRID_PASSWORD}
※1行です
SENDGRID_USERNAME、SENDGRID_PASSWORDという環境変数で認証情報が渡ってくるので、適当なプロパティ名つけて渡してやりましょう。mail.smtp.host、mail.smtp.port、mail.smtp.authについては、別にここで渡さなきゃいけないってことはないけども、設定値をハードコーディングしない的な意味でも、どうせJavaMailでPropertiesオブジェクトが必要だからこの方が楽という意味でも、システムプロパティとして渡してやった方が良いかと思います。
JavaMailでメール送信
あとはメール送るだけです。今回はJavaMail使います。
http://www.oracle.com/technetwork/java/javamail/index.html
もちろんmavenリポジトリ上にあるので、project/Build.scalaに1行追加すれば依存設定完了。
val appDependencies = Seq( // Add your project dependencies here, "javax.mail" % "mail" % "1.4.5" )
で、あとはJavaMailから、システムプロパティの値を使ってメールを送信してやるだけ。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers | |
import play.api._ | |
import play.api.mvc._ | |
object SendmailTest extends Controller { | |
def index = Action { | |
sendmail | |
Ok(views.html.index("ok")) | |
} | |
def sendmail = { | |
import java.util._ | |
import javax.mail._ | |
import javax.mail.internet._ | |
val props = System.getProperties | |
val auth = new Authenticator { | |
override val getPasswordAuthentication = | |
new PasswordAuthentication(props.getProperty("mail.smtp.user"), props.getProperty("mail.smtp.pass")) | |
} | |
val session = Session.getInstance(props, auth) | |
val msg = { | |
val m = new MimeMessage(session) | |
m.setFrom(new InternetAddress("hiro@nisshiee.org")) | |
m.setRecipients(Message.RecipientType.TO, "hiro@nisshiee.org") | |
m.setSubject("This is test mail from heroku", "ISO-2022-JP") | |
m.setSentDate(new Date) | |
m.setText("これはテストメールです", "ISO-2022-JP") | |
m | |
} | |
Transport.send(msg) | |
} | |
} |
※エラーハンドリングとかWebアプリ自体の認証とかせず、メール送信部分だけを記述しています
JavaMailの送信手順をScalaで記述しただけで、工夫とか何もしてませんけどね。
普通にこれで送信できます。
ね、簡単でしょ?