kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Mailtrap を使って受信メール確認を自動テストに組み込む

メール配信プラットフォーム「Mailtrap」を使うと,開発中にメールをテストしたり,実際にメールを配信したり,メール関連の悩みを幅広く解決できる❗️ちょうどメール関連のテスト戦略を設計していて,気になっていた Mailtrap の Email Testing を試してみた✌️

mailtrap.io

Mailtrap を本格的に使うなら Business Plan 以上にすると良さそう.1ヶ月に 50,000 件もメールを受信できるし,テストに使える専用メールアドレスも割り当てられる.しかし Free Plan でも1ヶ月に 100 件はメールを受信できるし(Inbox に残せるのは 50 件まで),Mailtrap API も使えるし,検証目的なら十分そう👌

mailtrap.io

\( 'ω')/ Mailtrap ならメールテストを自動テストにも組み込めるぞ〜

Project と Inbox 📩

まず,Mailtrap の画面で Project(プロジェクト)と Inbox(受信ボックス)を作る.今回は検証用に Sandbox ProjectSandbox Inbox という名前にした.

Project と Inbox

curl でメールを送信する 📩

次に Inbox に載っているサンプルコードを使って Mailtrap の SMTP 経由でメールを送信する.最初から準備されてるサンプルコードは Ruby on Rails / Django / Laravel など,計23種類ほどある(ちょっと選択肢は古めの感じもあるけど...).今回は一番お手軽に curl コマンドを使ってメールを送信することにした❗️

  • Command Line
    • cURL
  • Ruby
    • Ruby on Rails
    • Ruby (net/smtp)
  • Python
    • smtplib
    • Django
    • Flask-Mail
  • etc

ちなみに Mailtrap の Business Plan 以上だと Inbox email address 機能(専用メールアドレス)もある.アプリケーション側に実装してあるメール送信機能の宛先に指定することもできる💡使えるともっと良さそう〜

help.mailtrap.io

さっそく以下の curl コマンドを実行した(--user はマスキングしてある).

$ curl  \
--ssl-reqd \
--url 'smtp://sandbox.smtp.mailtrap.io:2525' \
--user 'xxxxx' \
--mail-from from@example.com \
--mail-rcpt to@example.com \
--upload-file - <<EOF
From: Magic Elves <from@example.com>
To: Mailtrap Inbox <to@example.com>
Subject: You are awesome!
Content-Type: multipart/alternative; boundary="boundary-string"

--boundary-string
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Congrats for sending test email with Mailtrap!

Inspect it using the tabs above and learn how this email can be improved.
Now send your email using our fake SMTP server and integration of your choice!

Good luck! Hope it works.

--boundary-string
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body style="font-family: sans-serif;">
    <div style="display: block; margin: auto; max-width: 600px;" class="main">
      <h1 style="font-size: 18px; font-weight: bold; margin-top: 20px">Congrats for sending test email with Mailtrap!</h1>
      <p>Inspect it using the tabs you see above and learn how this email can be improved.</p>
      <img alt="Inspect with Tabs" src="https://assets-examples.mailtrap.io/integration-examples/welcome.png" style="width: 100%;">
      <p>Now send your email using our fake SMTP server and integration of your choice!</p>
      <p>Good luck! Hope it works.</p>
    </div>
    <!-- Example of invalid for email html/css, will be detected by Mailtrap: -->
    <style>
      .main { background-color: white; }
      a:hover { border-left-width: 1em; min-height: 2em; }
    </style>
  </body>
</html>

--boundary-string--
EOF

すると,送信したメールが Inbox に届く❗️スパム分析 (Spam Analysis) や HTML チェック (HTML Check) 機能もある.メール本文のデザイン崩れなどをデバイスごとに確認できたりもする.便利〜

メールを受信できた

Mailtrap API でメールを取得する 📩

Mailtrap には Mailtrap API もあって,幅広い操作を自動化できる❗️

api-docs.mailtrap.io

1. Show email message

まず,Show email message API を実行して,メールを取得する.以下の値は Mailtrap の画面から事前に取得しておく📝 ちなみに今回は上に載せたメールを取得するために MESSAGE_ID を Mailtrap の画面から取得したけど,実際に使う場合はその前に Get messages API を実行して一覧を取得するのが良いと思う.

  • ACCOUNT_ID
  • INBOX_ID
  • TOKEN
  • MESSAGE_ID
$ ACCOUNT_ID=0000
$ INBOX_ID=0000000
$ TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ MESSAGE_ID=0000000000

$ curl -s "https://mailtrap.io/api/accounts/${ACCOUNT_ID}/inboxes/${INBOX_ID}/messages/${MESSAGE_ID}" \
>   --header 'Accept: application/json' \
>   --header "Api-Token: ${TOKEN}" | jq .
{
  "id": 0000000000,
  "inbox_id": 0000000,
  "subject": "You are awesome!",
  "sent_at": "2023-05-14T12:23:52.922Z",
  "from_email": "from@example.com",
  "from_name": "Magic Elves",
  "to_email": "to@example.com",
  "to_name": "Mailtrap Inbox",
  "email_size": 1632,
  "is_read": true,
  "created_at": "2023-05-14T12:23:52.923Z",
  "updated_at": "2023-05-14T12:25:30.445Z",
  "html_body_size": 952,
  "text_body_size": 228,
  "human_size": "1.6 KB",
  "html_path": "/api/accounts/0000/inboxes/0000000/messages/0000000000/body.html",
  "txt_path": "/api/accounts/0000/inboxes/0000000/messages/0000000000/body.txt",
  "raw_path": "/api/accounts/0000/inboxes/0000000/messages/0000000000/body.raw",
  "download_path": "/api/accounts/0000/inboxes/0000000/messages/0000000000/body.eml",
  "html_source_path": "/api/accounts/0000/inboxes/0000000/messages/0000000000/body.htmlsource",
  "blacklists_report_info": {
    "result": "success",
    "domain": "example.com",
    "ip": "93.184.216.34",
    "report": [
      {
        "name": "BACKSCATTERER",
        "url": "http://www.backscatterer.org/index.php",
        "in_black_list": false
      },
      {
        "name": "BARRACUDA",
        "url": "http://barracudacentral.org/rbl",
        "in_black_list": false
      },
      {
        "name": "Spamrbl IMP-SPAM",
        "url": "http://antispam.imp.ch/?lng=1",
        "in_black_list": false
      },
      {
        "name": "Wormrbl IMP-SPAM",
        "url": "http://antispam.imp.ch/?lng=1",
        "in_black_list": false
      },
      {
        "name": "LASHBACK",
        "url": "http://blacklist.lashback.com/",
        "in_black_list": false
      },
      {
        "name": "NIXSPAM",
        "url": "https://www.heise.de/ix/NiX-Spam-DNSBL-and-blacklist-for-download-499637.html",
        "in_black_list": false
      },
      {
        "name": "PSBL",
        "url": "https://psbl.org/",
        "in_black_list": false
      },
      {
        "name": "SORBS-SPAM",
        "url": "http://www.sorbs.net/lookup.shtml",
        "in_black_list": false
      },
      {
        "name": "SPAMCOP",
        "url": "http://spamcop.net/bl.shtml",
        "in_black_list": false
      },
      {
        "name": "TRUNCATE",
        "url": "http://www.gbudb.com/truncate/index.jsp",
        "in_black_list": false
      }
    ]
  },
  "smtp_information": {
    "ok": false
  }
}

api-docs.mailtrap.io

2. Get raw message

次にメール本文を取得するために Get raw message API や Get text message API を実行する.今回は Get raw message API を実行して,raw のまま取得する.

$ ACCOUNT_ID=0000
$ INBOX_ID=0000000
$ TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ MESSAGE_ID=0000000000

$ curl -s "https://mailtrap.io/api/accounts/${ACCOUNT_ID}/inboxes/${INBOX_ID}/messages/${MESSAGE_ID}/body.raw" \
>   --header 'Accept: text/plain, application/json' \
>   --header "Api-Token: ${TOKEN}"
From: Magic Elves <from@example.com>
To: Mailtrap Inbox <to@example.com>
Subject: You are awesome!
Content-Type: multipart/alternative; boundary="boundary-string"

--boundary-string
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Congrats for sending test email with Mailtrap!

Inspect it using the tabs above and learn how this email can be improved.
Now send your email using our fake SMTP server and integration of your choice!

Good luck! Hope it works.

--boundary-string
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body style="font-family: sans-serif;">
    <div style="display: block; margin: auto; max-width: 600px;" class="main">
      <h1 style="font-size: 18px; font-weight: bold; margin-top: 20px">Congrats for sending test email with Mailtrap!</h1>
      <p>Inspect it using the tabs you see above and learn how this email can be improved.</p>
      <img alt="Inspect with Tabs" src="https://assets-examples.mailtrap.io/integration-examples/welcome.png" style="width: 100%;">
      <p>Now send your email using our fake SMTP server and integration of your choice!</p>
      <p>Good luck! Hope it works.</p>
    </div>
    <!-- Example of invalid for email html/css, will be detected by Mailtrap: -->
    <style>
      .main { background-color: white; }
      a:hover { border-left-width: 1em; min-height: 2em; }
    </style>
  </body>
</html>

--boundary-string--

api-docs.mailtrap.io

Mailtrap と自動テストを組み合わせる 📩

Mailtrap API でメールを取得できるようになったので,活用例として自動テストと組み合わせることもできる❗️今回はサンプルとして Python の unittest と組み合わせたテストコードを書いてみた.メールを取得する get_message() とメール本文を取得する get_message_body()requests などの HTTP ライブラリを使って Mailtrap API を実行するように実装しつつ(今回は割愛),あとは from_emailsubjectbody など,重要な値をアサートしておくと良さそう💡

from mailtrap import Mailtrap
import unittest


class TestMailtrap(unittest.TestCase):
    def test_get_message(self):
        message = Mailtrap().get_message()
        self.assertEqual('from@example.com', message['from_email'])
        self.assertEqual('You are awesome!', message['subject'])

    def test_get_message_body(self):
        body = Mailtrap().get_message_body()
        self.assertIn('Good luck! Hope it works.', body)


if __name__ == '__main__':
    unittest.main()

実行すると...テスト2件とも成功している👏

..
----------------------------------------------------------------------
Ran 2 tests in 1.935s

OK

まとめ

メール配信プラットフォーム「Mailtrap」Email Testing を試してみた✌️

Mailtrap の機能は他にもまだまだたくさんあるし,引き続き検証を続けていくぞー❗️