カテゴリー
Linux

Docker コンテナ内の Laravel から外部サービスを使わずにメールを送信するために Docker コンテナ内に exim4 をインストールしたらできた、という記録

まとめ

MTA を構築するための Docker Compose コード

Docker Compose で exim4 を動かすための部分を抜粋します。

php/Dockerfile

  • --no-install-recommends を付ける場合は、 msmtpmailutils をインストールするものとして指定するだけでは肝心の 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

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

おわりに

やっぱりといいますか当然といいますか、あまり触れる機会がないためにメール送受信に関する経験が足りていません。。。そして、知識も足りていないために、苦労いたしました。

以上です。

コメントを残す