MailCatcherでメール送信をテストする
概要
メール送信のテストって面倒ですよね。本文の確認だけならそれほど手間ではありませんが、
やはりメールなので実際に送信できたかどうかの確認は必要になります。
すると、SMTPサーバを用意して、テストなり自分なりのアドレスに実際にメールを送って確認、
面倒なのでいつかオペミスしてホントの他人のアドレスに一斉送信とか、悲しいあるあるです。
で、なんかいいものは無いかと探しているとMailCatcherというのがあるようでした。
良い感じのライブラリだったのでdockerファイル作ってそれで開発用簡易SMTPサーバ(実際に送るわけではないですが)にすると便利であろうと思って試してみました。
環境
僕の環境はmacなのでdocker-machineを使っています。
なので、以降docker hostのIPアドレスは192.168.99.100としています。
ここは適宜ご自分の環境に合わせてください。
- ruby 2.3.0
- MailCatcher 0.6.4
- docker version 1.11.1, build 5604cbe
- docker-machine version 0.7.0,
MailCatcher
特徴としては
- SMTPサーバとして使えるが実際にメールを送信することはなく、送信したメールを保存してくれる。
- 保存したメールは
MailCatcherが別途用意しているweb画面でブラウザから確認できる。 - また保存されているメールを
apiで取得することが出来る
というようなライブラリです。
MailCatcherのDocker化
開発時にだけ必要なので出来るだけ軽いコンテナにしたかったためalpineベースのrubyコンテナを元に作りました。
FROM ruby:2.3.0-alpine
RUN apk --no-cache --update add \
libstdc++ \
build-base \
openssl-dev \
sqlite \
sqlite-dev \
ruby-dev && \
gem install mailcatcher && \
apk del build-base ruby-dev && \
rm -rf /tmp/* /var/tmp/* /var/cache/apk/*
EXPOSE 1025 1080
CMD ["mailcatcher", "-f", "--ip=0.0.0.0"]
このDockerfileの内容で作ったイメージをDocker hubにあげているので、buildしなくても、
下記コマンドでMailCatcherが立ち上がります。
docker run -d -p 1080:1080 -p 1025:1025 pocari/mailcatcher
ここでマッピングしている1080,1025はそれぞれ、web画面参照用のポート、SMTP用のポートです。
Web画面にアクセス
上記のコンテナ起動後、もうWeb画面も、SMTPサーバも使用可能になっているので、Web画面から確認してみます。
http://192.168.99.100:1080にブラウザからアクセスします。
まだメールは無いので何も表示されてませんが、シンプルで綺麗な画面ですね。
公式ページによるとWebSocketを使っているみたいで、メール送信が発生するとページをリロードしなくてもリアルタイムで画面が更新されていきます。
メール送信
さて、これで環境はできたので実際にメールを送信してみましょう。
やはりrailsから送ることが多いと思うので、今回はActionMailerを使ってテストしてみます。
たださすがにrailsのアプリケーションから作ると面倒なので、ActionMailer単体で使用します。
今回はplainなメールとHTMLメールをそれぞれ一通ずつ送信してみます。
Gemfile
Gemfileを作成してインストールします。
# Gemfile作成
$ bundle init
$ echo 'gem "actionmailer"' >> Gemfile
# インストール
$ bundle install --path=vendor/bundle
テスト用スクリプト
テスト用のスクリプトを書きます。
今回の場合SMTPサーバの設定のホストがdocker hostで、ポートがdocker run時に設定した1025です。
またHTMLメールも送ってみたいので、テンプレートファイルの置き場も別途指定します。
それ以外は通常のActionMailerの使い方と同じだと思います。
require 'action_mailer'
# SMTP設定
ActionMailer::Base.smtp_settings.merge!(
address: '192.168.99.100',
port: 1025
)
# テンプレートファイルの置き場所のルートフォルダを設定
ActionMailer::Base.prepend_view_path File.dirname(File.expand_path(__FILE__))
# メール送信クラス
class TestMailer < ActionMailer::Base
default from: 'from@example.com'
def test_mail(to, subject, body)
mail(to: to, subject: subject, body: body)
end
def test_html_mail(to, subject, arg1, arg2)
@arg1 = arg1
@arg2 = arg2
mail(to: to, subject: subject)
end
end
# 普通のメールを送信
TestMailer.test_mail(
'to_address@example.com',
'test subject',
'Hello, World'
).deliver_now
# HTMLメールを送信
TestMailer.test_html_mail(
'to_address@example.com',
'test subject',
'World',
'Hoge',
).deliver_now
テンプレートファイルも用意しておきます。
今回はテンプレートファイルのルートをスクリプトファイルのディレクトリにしたので、
テンプレートファイルは./test_mailer/test_html_mail.html.erbに置きます。
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Hello, <%= @arg1 %></h1>
<h2>This is HTML mail.</h2>
<p>arg2 is <%= @arg2 %></p>
</body>
</html>
実行!
さて、上記までで準備出来たので実行してみましょう。
$ bundle exec ruby test.rb
先ほどのweb画面にアクセスると下記のようになっていると思います。
きちんと保存されていますね。
API
APIの方も確認してみましょう。
192.168.99.100:1080/messagesで保存済みメールのサマリが取得できます。
(ここではjsonの整形にjqを使ってます。)
$ curl -s 192.168.99.100:1080/messages | jq
[
{
"id": 1,
"sender": "<from@example.com>",
"recipients": [
"<to_address@example.com>"
],
"subject": "test subject",
"size": "296",
"created_at": "2016-05-19T15:31:32.000+00:00"
},
{
"id": 2,
"sender": "<from@example.com>",
"recipients": [
"<to_address@example.com>"
],
"subject": "test subject",
"size": "517",
"created_at": "2016-05-19T15:31:32.000+00:00"
}
]
個別メールの本文もapiで取得できます。メールの識別は上記のサマリ結果のidを使い
192.168.99.100:1080/messages/:id(.format)
の形式で確認できます。.formatの部分はplainやらhtmlやらです。
今回の場合id:1はplain、id:2はhtmlなので、そのようにして内容を確認してみます。
- テキストメールの内容
$ curl -s 192.168.99.100:1080/messages/1.plain
Hello, World
- HTMLメールの内容
$ curl -s 192.168.99.100:1080/messages/2.html
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Hello, World</h1>
<h2>This is HTML mail.</h2>
<p>arg2 is Hoge</p>
</body>
</html>
きちんと取れてますね。
その他:id.sourceの形式でヘッダも含めたメール内容全体が取得できます。
$ curl -s 192.168.99.100:1080/messages/2.source
Date: Fri, 20 May 2016 00:31:32 +0900
From: from@example.com
To: to_address@example.com
Message-ID: <573ddc543bc77_8ff73fcdbe03fa18274e5@paganini.local.mail>
Subject: test subject
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Hello, World</h1>
<h2>This is HTML mail.</h2>
<p>arg2 is Hoge</p>
</body>
</html>
まとめ
これなら安心して開発環境でバンバンメール送信できますね。


