メール送信機能をgoのアプリケーションにつけようと思ったけど、どうやってやろうかなー、と。で、ローカルではdockerでメールサーバー用意して、本番ではsendgridで行うようにした。
メール送信のパッケージにはgomailというものを使ってやるかな。
gomailを使ってメール送信する
以下のパッケージを使ってgoでメール送信をしようと思う。star数結構あるしね。ただ、コミットが数年前だったりするからなんとも言えない。
$ go get gopkg.in/gomail.v2
実装
とりあえず、サクッと試したいなら以下の記事にように書くと動くと思われる。
ローカルではmailhogを使う
ローカルでいちいちメール飛ばすのは怖いからブラウザでメールが確認できるものを使おう。mailhogだ。 dockerでアプリケーションを立ち上げているんだけど、mailhogにもimageがあるから別でコンテナを立ち上げて使うようにする。
docker-compose.ymlにmailhogの記述をする。
mailhog: image: mailhog/mailhog ports: - "8025:8025"
これでdocker-compose up
して、ブラウザで8025番ポートでアクセスすればこんな画面になる。
mailhogを使ってメール送信をすると、この画面にどんなメールが送信されたのかという内容が表示される。
あとは下記のSend()内にあるようなプログラムを書けば、メールがMailhogで確認できた。
package mailer import ( gomail "gopkg.in/gomail.v2" ) type GoMailer struct { Message *gomail.Message } func NewMailer() *GoMailer { return &GoMailer{ Message: gomail.NewMessage(), } } func (mailer *GoMailer) Send() { mailer.Message.SetHeader("From", "test@example.com") mailer.Message.SetHeader("To", "test@example.com") mailer.Message.SetHeader("Subject", "Hello!") mailer.Message.SetBody("text/plain", "Hello!") d := gomail.Dialer{Host: "mailhog", Port: 1025} if err := d.DialAndSend(mailer.Message); err != nil { panic(err) } }
Host名は、docker-composeで指定したコンテナ名。Portは1025番で待ち受けているみたいね。
本番環境(heroku)ではsendgridを使う
今回はherokuでgoのアプリケーションを使っているから、herokuのアドオンを使ってメール送信しようと思う。まあ、メール送信といったらSendgridだよね。アドオン使うけど、別にアドオン使わないでもSendgridのAPI_KEYなんかを使えばメール送信できるはず。
heroku公式にアドオンの追加方法が書いてあるから、これを参考にやる。
$ heroku addons:create sendgrid:starter
アドオンを追加したらsendgridのusernameとpasswordが勝手に発行されるっぽいね。以下でSENDGRID_USERNAME
とSENDGRID_PASSWORD
が参照できる。
$ heroku config:get SENDGRID_USERNAME $ heroku config:get SENDGRID_PASSWORD
ドキュメントを読んでいると、API_KEYを使ったメール送信方法が書いてあるけど、今回はAPI_KEYは使わないでいきたいんだよなあ。(ローカル用と本番用の記述が結構変わってしまいそうなので・・・)
なんかActionMailerの実装方法はちょっと載っているから、それを参考にしてgomailを使った実装する。やっぱりRailsでHeroku使う人が多いんだろうなあ。
var d *gomail.Dialer if os.Getenv("ENV") == "prod" { d = gomail.NewDialer("smtp.sendgrid.net", 587, os.Getenv("SENDGRID_USERNAME"), os.Getenv("SENDGRID_PASSWORD")) } else { d = gomail.NewDialer("mailhog", 1025, "", "") } if err := d.DialAndSend(mailer.Message); err != nil { panic(err) }
ちょっと記述変えた。本番環境では、sendgridを使ってローカル環境ではmailhogを使う。
gomailにNewDialerという関数があるんだけど、これ使えなかったから調べたら以下で解決した。dep問題だったか。
で、このsendgrid使ったメール送信処理を自分のアドレスに向けて実行すれば、メールが受信されるはず。ただ、すぐ来るわけじゃなくてちょっとラグがあるね。
メール送信のアクティビティは、herokuの管理画面からsendgridアドオンへ飛んで確認することができるみたいね。
まとめ
うーん、最初からAPI_KEY使う方針で考えた方が楽だったかもな。あとgomailコードの中見ないとあんま使い方わからんかもしれん。