まとめ
- MTA として exim4 (Exim Internet Mailer) を使う。
- exim4 を php:apache コンテナにインストールする。
- PHP からメールを送信できるようになった。
- Laravel から sendmail ドライバーでメールを送信できるようになった。
- 次のページが大いに参考になった (ありがとうございます!) 。
MTA を構築するための Docker Compose コード
Docker Compose で exim4 を動かすための部分を抜粋します。
php/Dockerfile
--no-install-recommends
を付ける場合は、msmtp
とmailutils
をインストールするものとして指定するだけでは肝心のexim4
がインストールされなかった。そのため、 imixs-docker/Dockerfile at master · imixs/imixs-docker を参考に、exim4-daemon-light
を追加した。exim4
をインストール後に設定ファイルをコピーした。このため最後にreload
を必要とした。おそらくexim4
インストール前に設定ファイルのコピーを済ませておけばreload
は不要となる可能性がある。しかし、今後の Dockerfile の編集でreload
を忘れて動かない可能性を発生させたくないため、明示的にreload
するようにした。exim4
のコマンドなどservice exim4 status
service exim4 reload
- ログファイル
/var/log/exim4/mainlog
FROM php:7.4.16-apache AS shared
... 略 ...
# sendmail
RUN apt-get update && apt-get install -y --no-install-recommends \
exim4-daemon-light \
mailutils \
msmtp \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY ./php/php/sendmail.ini /usr/local/etc/php/conf.d/
COPY ./php/exim4/update-exim4.conf.conf /etc/exim4/update-exim4.conf.conf
RUN service exim4 reload
php/php/sendmail.ini
- PHP の sendmail_path デフォルト値 を考えると今回のケースでは不要かもしれない。
sendmail_path = /usr/sbin/sendmail -t
php/exim4/update-exim4.conf.conf
- 参考ページそのままで、それぞれのパラメータの意味は正直よくわかっていない。
dc_eximconfig_configtype='internet'
dc_other_hostnames=''
dc_local_interfaces='127.0.0.1;::1'
dc_readhost='exim4'
dc_relay_domains=''
dc_minimaldns='true'
dc_relay_nets=''
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname='true'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
PHP からメール送信するプログラムコード
mail.php
- 使い方:
php mail.php
$to
のみ変更して実行してみたところ、結果は Gmail にメールを送信することができました。そもそも届かなかったり、届いても迷惑メール扱いとなると予想していただけに、びっくりしました。
<?php
mb_language("Japanese");
mb_internal_encoding("UTF-8");
$to = 'to@example.com'; // 実際のテスト送信先に修正すること
$subject = "テスト"; // 題名
$body = "これはテストです。\n"; // 本文
$from = "xxxxxx@example.com";
$header = "From: $from\nReply-To: $from\n";
$ret = mb_send_mail($to, $subject, $body, $header);
var_export($ret);
Laravel 6 からメールを送信するコード
メール 6.x Laravel を参考にして mailable クラスを生成して、、、というのが実際のシステム構築の際に行うことですけれども、今回はお試しなのでコマンドラインから試しました。
結果は、 Gmail には送れず、 Yahoo!メールには送ることができました。ということは、コードとしては、これで問題ない、と言えます。また、 PHP の mb_send_mail 関数では Gmail に届くけれども、 Laravel 6 のメール送信の仕組みでは届かない、という少し複雑な結果となりました。時が立つなどして状況が変われば、 mb_send_mail からでも Gmail に届かなくなるかもしれません。
php artisan tinker
// `to()` は実際のテスト送信先に修正すること
Mail::raw('これはテストです。php artisan tinker から送信した。', function($m) { $m->subject('これはテストです tinker')->from('xxxxx@example.com', 'Laravel')->to('to@example.com'); });
まだよく理解できていないこと
今回 MTA をローカルに用意して設定して Laravel からは sendmailドライバーを使ってメール送信しました。 SMTP ドライバーを使う場合は、 sendmail コマンドを用意しなくても良いのでしょうか? 次のページを見ていると、そんなことはないように思ます。
- https://shnr.net/blog/?p=857 (本投稿を書いている間にリンク切れになっていた。。。)
ローカル MTA に SMTP 設定をし、 Laravel .env にも SMTP 設定をして送信成功した例です。 2回 SMTP 設定する必要があるのかどうか、謎です。
おまけ。メール送信ログ、 OK 集、 NG 集。
まずは PHP の mb_send_mail 関数でメール送信を試した時のログです。
↓ NG . 設定ファイルの内容がダメだった? (覚えていない。。。)
2021-07-10 21:15:10 1m2KJa-000018-Gb <= root@localhost U=root P=local S=496
2021-07-10 21:15:10 1m2KJa-000018-Gb ** yyyyyy@gmail.com R=nonlocal: Mailing to remote domains not supported
2021-07-10 21:15:10 1m2KJa-00001B-HG <= <> R=1m2KJa-000018-Gb U=Debian-exim P=local S=1692
2021-07-10 21:15:10 1m2KJa-000018-Gb Completed
2021-07-10 21:15:10 1m2KJa-00001B-HG => /var/mail/mail <root@localhost> R=mail4root T=address_file
2021-07-10 21:15:10 1m2KJa-00001B-HG Completed
↓ OK
2021-07-10 21:21:59 1m2KQB-0000Dj-ME <= root@localhost U=root P=local S=496
2021-07-10 21:22:00 1m2KQB-0000Dj-ME H=gmail-smtp-in.l.google.com [2404:6800:4008:c07::1a] Cannot assign requested address
2021-07-10 21:22:01 1m2KQB-0000Dj-ME => yyyyyy@gmail.com R=dnslookup T=remote_smtp H=gmail-smtp-in.l.google.com [64.233.189.26] X=TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=yes DN="CN=mx.google.com" K C="250 2.0.0 OK r15si13227158pls.336 - gsmtp"
2021-07-10 21:22:01 1m2KQB-0000Dj-ME Completed
ここからは Laravel で送信を試しました。
↓ ok. Gmail に送信できた。
2021-07-11 21:58:34 1m2hT8-00002N-15 <= xxxxx@example.com U=root P=local S=706 id=79c6c1233118060a6424af2e3f08d680@swift.generated
2021-07-11 21:58:35 1m2hT8-00002N-15 H=gmail-smtp-in.l.google.com [64.233.189.27]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. b6si7677530plx.347 - gsmtp
2021-07-11 21:58:36 1m2hT8-00002N-15 H=alt1.gmail-smtp-in.l.google.com [142.250.141.27]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. l20si2909577pjz.91 - gsmtp
2021-07-11 21:58:38 1m2hT8-00002N-15 H=alt2.gmail-smtp-in.l.google.com [142.250.115.27]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. y22si13498059oti.68 - gsmtp
2021-07-11 21:58:40 1m2hT8-00002N-15 H=alt3.gmail-smtp-in.l.google.com [64.233.171.27]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. t42si14417023oiw.93 - gsmtp
↓ NG. Gmail には最初のメールは送信できたが、2回目からは届かなくなった。 Gmail 側の対策と思われる。
2021-07-11 22:00:41 1m2hVB-00002c-Nw <= xxxxx@example.com U=root P=local S=706 id=482a831590c42f4dcb39f565041b73c7@swift.generated
2021-07-11 22:00:43 1m2hVB-00002c-Nw H=gmail-smtp-in.l.google.com [2404:6800:4008:c07::1b] Cannot assign requested address
2021-07-11 22:00:44 1m2hVB-00002c-Nw H=gmail-smtp-in.l.google.com [64.233.189.26]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. j9si5446201pga.313 - gsmtp
2021-07-11 22:00:46 1m2hVB-00002c-Nw H=alt1.gmail-smtp-in.l.google.com [142.250.141.26]: SMTP error from remote mail server after pipelined end of data: 421-4.7.0 This message does not have authentication information or fails to pass\n421-4.7.0 authentication checks. To best protect our users from spam, the\n421-4.7.0 message has been blocked. Please visit\n421-4.7.0 https://support.google.com/mail/answer/81126#authentication for more\n421 4.7.0 information. d16si14154506oiw.272 - gsmtp
↓ ok. yahoo.co.jp 。送信できた。ただし、迷惑メール扱いとなっていた。
021-07-13 21:26:36 1m3PvI-0000DE-6G <= xxxxx@example.com U=root P=local S=720 id=c99da69d64f7f81011b20959644775dc@swift.generated
2021-07-13 21:26:37 1m3PvI-0000DE-6G => yyyyyy@yahoo.co.jp R=dnslookup T=remote_smtp H=mx3.mail.yahoo.co.jp [202.93.78.241] C="250 ok dirdel"
2021-07-13 21:26:37 1m3PvI-0000DE-6G Completed
おわりに
やっぱりといいますか当然といいますか、あまり触れる機会がないためにメール送受信に関する経験が足りていません。。。そして、知識も足りていないために、苦労いたしました。
以上です。