ローカルテスト用SMTPメールサーバは Mailpit がオススメ！

## はじめに

長らくローカルテスト用のメールサーバとして [MailHog](https://github.com/mailhog/MailHog) ([DockerHub](https://hub.docker.com/r/mailhog/mailhog)) を使ってきたのですが、以下のような不満がありました。

- 今現在(2024)メンテナンスが行われていない
- ローカル開発用とはいえ、UXが厳しい（日本語を受け付けてくれない）
- アーキテクチャが amd64 しか対応していない

そこで、MailHogよりベターな選択肢はないか調査してみたところ、 [Mailpit](https://github.com/axllent/mailpit) ([DockerHub](https://hub.docker.com/r/axllent/mailpit)) が以下の点で良いと感じ実際に使っているので、この記事で紹介します。

- 今現在(2024)メンテナンスが行われている
- 良いUX。ちゃんと日本語でメールを検索できる
- アーキテクチャとして arm にも対応している (amd64/arm64/i386)
- ほか好ましい点
    - サーバ再起動後にちゃんとデータが残る (sqlite形式で残るようです)
    - Goで実装されていて動作が軽い
        - Goなのでシングルバイナリとしても動作できる
        - いざとなったら自分で改造するのも簡単！
    - REST APIでメールを検索できる
    - リアルタイムで通知が分かる
    - [その他豊富な機能](https://mailpit.axllent.org/docs/)

## Mailpit を使ってみる

### Docker Compose で立ち上げる

以下の `compose.yml` で立ち上げることができます。設定ファイルは一切不要です。データ(sqlite形式のDBファイル)は `./mailpit` 以下に保存されるようになっています。

```compose.yml
services:
  mail:
    # Web画面: http://localhost:19980
    image: axllent/mailpit:latest
    ports:
      - "19925:1025"
      - "19980:8025"
    volumes:
      - ./mailpit:/data
    environment:
      TZ: Asia/Tokyo
      MP_MAX_MESSAGES: 5000
      MP_DATABASE: /data/mailpit.db
      MP_SMTP_AUTH_ACCEPT_ANY: 1
      MP_SMTP_AUTH_ALLOW_INSECURE: 1
```

```sh
$ docker compose up -d
```

SMTPポートは `localhost:19925` に、Web画面は `http://localhost:19980` に開いています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/05caa52a-7674-9653-dc57-8dd816fcb9db.png)

なお、Web画面はレスポンシブ対応のようです。


### メールを試しに送信してみる

立ち上げたMailpit宛にPython3でテストメールを送信してみます。

```python:send_mail.py
#!/usr/bin/env python3

import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

smtp_server = "localhost"
smtp_port = 19925

from_email = "sender@example.com"
from_name = "Sender Name"
to_email = "recipient@example.com"
to_name = "Recipient Name"

subject = "テストメール"
body = "これはテストメールです。"

# メールのメッセージを作成
msg = MIMEText(body, "plain", "utf-8")
msg["From"] = formataddr((from_name, from_email))
msg["To"] = formataddr((to_name, to_email))
msg["Subject"] = subject

# SMTPサーバーに接続してメールを送信
try:
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.sendmail(from_email, [to_email], msg.as_string())
    print("メールが送信されました")
except Exception as e:
    print(f"メールの送信に失敗しました: {e}")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/d1e0a108-9b69-705e-aaef-c17f4736edb0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/d6bd9466-b23c-df63-e71d-84f1ea0ce5ff.png)

メールが届くと、リアルタイムにブラウザのアイコンに反映されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/fc098752-69a1-b1fa-2c05-8b022465dddc.png)

また、画面左下のベルのマークを押下してプッシュ通知を有効にすることにより、プッシュ通知を受け取ることもできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/0b1cf6f7-0d18-2968-0815-4bd22f585031.png)



### API を使って送信したメールを検索してみる

E2E試験や統合試験などで、アプリケーションが特定のメールを送ったことを自動テストしたいことがあると思いますが、そういったケースに使えるかチェックしてみます。

MailpitはそういったケースのためにREST APIを備えており、`http://Web画面のアドレス/api/v1/` 以下でREST APIドキュメントにアクセスすることができます。

今回のセットアップであれば `http://localhost:19980/api/v1/` でAPIドキュメント、もともとのSwagger定義を `http://localhost:19980/api/v1/swagger.json` で取得することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1577592/b962e542-e0cc-89cd-1d86-032d592f7f8c.png)

API操作に対応するcurlコマンドを確認できるほか、直接ドキュメント上からAPIを実行することも可能です。

実際にcurlコマンドを実行してみます。

```sh:curlコマンドを実行して検索APIを叩いてみる
# ?query=これはテストメールです
$ curl -X GET "http://localhost:19980/api/v1/search?query=%E3%81%93%E3%82%8C%E3%81%AF%E3%83%86%E3%82%B9%E3%83%88%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%99" \
 -H "accept: application/json" | jq

{
  "total": 1,
  "unread": 0,
  "count": 1,
  "messages_count": 1,
  "start": 0,
  "tags": [],
  "messages": [
    {
      "ID": "VDxtyh9qXyGpPAkFddZMED",
      "MessageID": "HibCLGXnV53UDUCPg3tjfn@mailpit",
      "Read": true,
      "From": {
        "Name": "Sender Name",
        "Address": "sender@example.com"
      },
      "To": [
        {
          "Name": "Recipient Name",
          "Address": "recipient@example.com"
        }
      ],
      "Cc": [],
      "Bcc": [],
      "ReplyTo": [],
      "Subject": "テストメール",
      "Created": "2024-09-25T18:58:11.93+09:00",
      "Tags": [],
      "Size": 551,
      "Attachments": 0,
      "Snippet": "これはテストメールです。"
    }
  ]
}
```

先ほど送信したメールを含むJSONが取れました！


## まとめ

同ジャンルのローカルテスト用のSMTPサーバは検索すればかなりあるのですが、動作が軽い・マルチアーキテクチャ・求めている機能(UX・REST API・データ永続性)を満たしているという点で **[Mailpit](https://github.com/axllent/mailpit)は文句のつけようがない完成度** と感じました。

**テスト用のSMTPサーバとして[Mailpit](https://github.com/axllent/mailpit)は非常におすすめです。**