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>
まとめ
これなら安心して開発環境でバンバンメール送信できますね。