メール送信テストツールMailHogの設定

isdはじめに

先日、LinuxサーバーにMailHogをインストール、設定する機会がありました。

インターネット上に参考情報があるため、MailHogをインストールして起動すること自体はそれほど難しくなかったのですが、サーバーの運用としては、少し工夫が必要でしたので、ここにまとめておきます。

MailHogは、アプリケーションから送信したメールを確認するためのテストツールです。

・MailHog – GitHub MailHog
https://github.com/mailhog/MailHog

受信メール確認のWebUIと、そのテスト用メールボックスに送信するためのSMTP機能を備えており、インターネットへのリアルメール送信が難しいPCの開発環境で使用されることが多いでしょう。

今回は、Linuxサーバー上にMailHogをインストール、設定します。
OSは、AlmaLinux 9です。

isd設定手順

インストール、設定手順としては、以下を参考にしました。
ありがとうございます。

・Mailhog_installation.md – GitHub dipenparmar12
https://gist.github.com/dipenparmar12/4e6cd50d8d1303d5e914742f62659116

・MailHog をリバースプロキシに通したら Error during WebSocket handshake: Unexpected response code: 400 と怒られたときに読むページ – Qiita
https://qiita.com/yokra9/items/2094626f3339cca5c5b8

  1. MailHogのインストール
  2. Systemdのサービスとして登録、起動
  3. ログ出力設定
  4. Apacheのリバースプロキシ設定

1. MailHogのインストール

GitHubからビルド済み MailHog のバイナリをダウンロードするのが手っ取り早いでしょう。

・MailHog Releases – GitHub MailHog
https://github.com/mailhog/MailHog/releases

※そうすれば、Goをインストールする必要もありません。

今回は、wgetコマンドでダウンロードして、/usr/local/bin/mailhog としてインストールし、実行権限を付与します。

 # wget https://github.com/mailhog/MailHog/releases/download/v1.0.1/MailHog_linux_amd64 \
    -O /usr/local/bin/mailhog

 # chmod +x /usr/local/bin/mailhog

 # ls -l /usr/local/bin/mailhog

-rwxr-xr-x 1 root root 13367472 12月  7  2021 /usr/local/bin/mailhog

 

一時的に MailHog を起動してみます。

 # mailhog

2024/12/13 16:24:05 Using in-memory storage
2024/12/13 16:24:05 [SMTP] Binding to address: 0.0.0.0:1025
[HTTP] Binding to address: 0.0.0.0:8025
2024/12/13 16:24:05 Serving under http://0.0.0.0:8025/
Creating API v1 with WebPath:
Creating API v2 with WebPath:

 

↑起動時のメッセージ出力から、MailHogは
SMTPはTCP/1025ポート
WebUIはTCP/8025ポート
を使用していることがわかります。

サーバーのWebブラウザコマンドから管理画面にアクセスしてみます。
ここでは、lynxを使用していますが、wgetやcurlでダウンロードして、index.html を確認しても構いません。

 $ lynx http://0.0.0.0:8025/

   MailHog MailHog
   ____________________
   Find messages containing {{ searchText }} Find messages to {{
   searchText }} Find messages from {{ searchText }}
     * GitHub GitHub

     * {{ hasEventSource ? 'Connected' : 'Disconnected' }}
     * Inbox ({{totalMessages}})
     * Delete all messages
...

 

それっぽいページが表示されることを確認できたら、mailhogコマンドを起動したターミナルで、Ctl-Cで、mailhogを終了します。

2. Systemdのサービスとして登録、起動

サーバー上で管理しやすいよう、MailHog を Systemd のサービスとして登録します。

Unitファイルを作成します。

※参考記事では、ExecStart で mailhog を起動するコマンドの先頭に /usr/bin/env が付与されているものもありますが、そうすると、この後のrsyslog設定でログを扱う際のプログラム名が env となってしまうため、ここでは付与しません。

 # vim /etc/systemd/system/mailhog.service

--
[Unit]
Description=Mailhog
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mailhog > /dev/null 2>&1 &

[Install]
WantedBy=multi-user.target
--

 

MailHogサービスを起動、自動起動設定します。

 # systemctl enable --now mailhog

--
Created symlink /etc/systemd/system/multi-user.target.wants/mailhog.service → /etc/systemd/system/mailhog.service.
--

 # systemctl status mailhog | less

--
● mailhog.service - Mailhog
   Loaded: loaded (/etc/systemd/system/mailhog.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2024-12-13 17:07:43 JST; 1s ago
 Main PID: 1520799 (mailhog)
    Tasks: 4 (limit: 5742)
   Memory: 2.4M
   CGroup: /system.slice/mailhog.service
           mq1520799 /usr/local/bin/mailhog > /dev/null 2>&1 &

12月 13 17:07:43 hostname systemd[1]: Started Mailhog.
12月 13 17:07:43 hostname mailhog[1520799]: 2024/12/13 17:07:43 Using in-memory storage
12月 13 17:07:43 hostname mailhog[1520799]: 2024/12/13 17:07:43 [SMTP] Binding to address: 0.0.0.0:1025
12月 13 17:07:43 hostname mailhog[1520799]: [HTTP] Binding to address: 0.0.0.0:8025
12月 13 17:07:43 hostname mailhog[1520799]: 2024/12/13 17:07:43 Serving under http://0.0.0.0:8025/
12月 13 17:07:43 hostname mailhog[1520799]: Creating API v1 with WebPath:
12月 13 17:07:43 hostname mailhog[1520799]: Creating API v2 with WebPath:
--

 

プログラム名「mailhog」としてログが出力されています。
「Creating API v1 with WebPath:」とあるので、無事起動したようです。

3. ログ出力設定

MailHogサービスを無事起動できましたが、このままでは、/var/log/messages に毎分以下のようなログが出力されます。

 # less /var/log/messages

Dec 13 17:08:43 hostname mailhog[1520799]: [APIv1] KEEPALIVE /api/v1/events
Dec 13 17:09:43 hostname mailhog[1520799]: [APIv1] KEEPALIVE /api/v1/events
Dec 13 17:10:43 hostname mailhog[1520799]: [APIv1] KEEPALIVE /api/v1/events

 

このままでは、/var/log/messages の重要なメッセージが検出しにくいため、rsyslogの設定で、MailHogサービスのログは、専用の /var/log/mailhog に出力するようにします。

※Systemd Unit設定の ExecStart で /usr/bin/env を指定しなかったことで、「programname が mailhog であれば~」というログフィルター設定が可能となります。

 # vim /etc/rsyslog.d/mailhog.conf

--
:programname, isequal, "mailhog" /var/log/mailhog.log
& stop
--

 

rsyslogを再起動して反映し、正しく起動したことを確認します。

※rsyslogの設定が間違っていると、rsyslogが停止し、syslogが全く出力されないこともあるため、注意しましょう。

 # systemctl restart rsyslog

 # systemctl status rsyslog

--
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor pre>
   Active: active (running) since Fri 2024-12-13 17:14:10 JST; 3s ago
     Docs: man:rsyslogd(8)
           https://www.rsyslog.com/doc/
 Main PID: 1521247 (rsyslogd)
    Tasks: 3 (limit: 5742)
   Memory: 9.6M
   CGroup: /system.slice/rsyslog.service
           mq1521247 /usr/sbin/rsyslogd -n

12月 13 17:14:10 hostname systemd[1]: Starting System Logging Service...
12月 13 17:14:10 hostname systemd[1]: Started System Logging Service.
12月 13 17:14:10 hostname rsyslogd[1521247]: [origin software="rsyslogd" swVers>
12月 13 17:14:10 hostname rsyslogd[1521247]: imjournal: journal files changed,
--

 

MailHogサービスのログが /var/log/mailhog.log に出力され、/var/log/messages には出力されないことを確認します。

 # less /var/log/mailhog.log

Dec 13 17:14:43 hostname mailhog[1520799]: [APIv1] KEEPALIVE /api/v1/events
Dec 13 17:15:43 hostname mailhog[1520799]: [APIv1] KEEPALIVE /api/v1/events

 # less /var/log/messages

 

/var/log/maillog.log のログローテートを設定します。
以下は、週次でローテートし、1年間保存する例です。

 # vim /etc/logrotate.d/mailhog

--
/var/log/mailhog.log {
    weekly
    rotate 52
    compress
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /bin/systemctl restart mailhog > /dev/null 2>/dev/null || true
    endscript
}
--

 

4. Apacheのリバースプロキシ設定

受信メール確認のWebUIを、インターネット経由でアクセスできるようにします。
ここでは、WebUIのURLは、以下とします。

https://example.jp/mailhog/

ドメイン example.jp の Apache VirtualHost Config で、URLパス /mailhog/ へのアクセスを MailHog WebUI のTCP/8025ポートへ転送するリバースプロキシ設定を追記します。
MailHogは WebSocket を使用しているため、リバースプロキシでも WebSocket を通すよう、proxy_wstunnel モジュールを使用するのがポイントです。
(ws:// を含む行。)

 # vim /etc/httpd/conf.d/vhost_ssl_example.jp.conf

--
...
# MailHog WebUI
ProxyPass /mailhog/api/v2/websocket ws://0.0.0.0:8025/api/v2/websocket
ProxyPassReverse /mailhog/api/v2/websocket ws://0.0.0.0:8025/api/v2/websocket
ProxyPass /mailhog/ http://0.0.0.0:8025/
ProxyPassReverse /mailhog/ http://0.0.0.0:8025/
...
--

 

mod_proxy, mod_proxy_http, mod_proxy_wstunnel モジュールのLoadが有効となっていることを確認します。

 # vim /etc/httpd/conf.modules.d/00-proxy.conf

--
...
LoadModule proxy_module modules/mod_proxy.so
...
LoadModule proxy_http_module modules/mod_proxy_http.so
...
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
...
--

 

Apacheを再起動して反映します。

 # apachectl configtest
 # systemctl restart httpd

 

第三者にアクセスされないよう、必要に応じて、BASIC認証やアクセス元IPアドレスの制限を追加しておくとよいでしょう。

ちなみに、Nginxの場合は、こんな設定になります。
こちらも、リバースプロキシでもWebSocketを通すようにするのがポイントです。

    # MailHog WebUI
    location /mailhog/ {
        chunked_transfer_encoding on;
        proxy_pass http://0.0.0.0:8025/;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_redirect off;
        proxy_buffering off;
    }

 

(参考)
・MailHog not working when using nginx proxy pass – GitHub MailHog
https://github.com/mailhog/MailHog/issues/117
 

Apache(もしくはNginx)の設定が完了したので、WebブラウザからWebUIにアクセスしてみます。
https://example.jp/mailhog/

以下のようなWebUIページが表示されればOKです。

isdメール送信テスト

PHPアプリケーションからのメール送信テストを実施します。

(参考)
・Docker ComposeでMailHogコンテナを組み合わせてメール送信の動作確認
https://zenn.dev/qljmssqh/articles/5e38a3c9123018

・DockerでMailHogを使ってPHPのメール送信確認をする
https://qiita.com/ran/items/0dede7d3f28601b2ad96

まず、PHPからのメール送信でMailHogのSMTPに送信するよう、php.ini の sendmail_path パラメータを変更し、Linuxサーバーのsendmailコマンドではなく、MailHogコマンドを使用して送信するようにします。

 # vim /etc/php.ini

--
;sendmail_path = /usr/sbin/sendmail -t -i
sendmail_path = /usr/local/bin/mailhog sendmail
--

 

PHP-FPMを再起動して反映します。

 # systemctl restart php-fpm

 

サーバーに、メール送信テスト用PHPページを設置します。

 # vim <DocumentRoot>/sendmail_test.php

--
<?php
$from = 'from@example.jp';
$to   = 'to@example.com';
$subject = 'テストメール';
$body = 'MailHogのメール送信テストです。';
$header = "From: ".$from."\r\n";

$ret = mb_send_mail($to, $subject, $body, $header);
var_dump($ret);
--

 

ブラウザからメール送信テスト用PHPページのURLにアクセスすることで、PHPを実行します。
https://example.jp/sendmail_test.php

MailHogのWebUIページで、受信メールを確認します。

↑無事、メールが届いたことと、メールの内容を確認できました。
うまくいかない場合は、MailHogのログや、Apacheのアクセスログ、エラーログを確認、調査するとよいでしょう。

なお、php.ini で、
mbstring.language = Japanese
を設定している場合、メール送信時の文字コードが ISO-2022-JP となりますが、MailHogは ISO-2022-JP に非対応のようで、WebUIでメールの日本語が文字化けして表示されます。

この場合は、メール送信テストのPHPで、UTF-8で送信するよう工夫が必要なようです。
以下などを参考にするとよいでしょう。

(参考)
・mb_send_mailで送ったメールをMailHogで受け取ると文字化けする – teratail
https://teratail.com/questions/318732

・PHPマニュアル mb_language
https://www.php.net/manual/ja/function.mb-language.php

isdおわりに

メール送信テストツールMailHogをLinuxサーバーにインストール、設定する手順をまとめました。
PCの開発環境で動作させる場合と違い、インターネット上のLinuxサーバーで運用する場合は、Webのリバースプロキシ設定や、ログ出力設定で、少し工夫が必要です。

 

Follow me!