メールサーバを自作し、imap_open でメールサーバにある受信メールを取得するプログラムを作成していた際に遭遇したエラーとその対処法について。
SSL / TLS を使用して POP3 / IMAP でメールを取得しようとしたところエラーが発生。
ErrorException
imap_open(): Couldn't open stream {localhost:993/imap/ssl}INBOX
PHP Fatal error: Uncaught ErrorException: Unknown: Certificate failure for localhost: Server name does not match certificate: /CN=example.com (errflg=2) in Unknown:0
Stack trace:
#0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions→handleError()
#1 {main}
thrown in Unknown on line 0
dovecot: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=127.0.0.1, lip=127.0.0.1, TLS, session=<XXXXXXXXXXXXXXX>
Postfix と Dovecot に SSL/TLS を導入する前は imap_open が成功していました。 (POP3:110番ポート、IMAP:143番ポート)
$account = 'mail@example.com'; $password = 'PASSWORD'; # POP3 で接続(成功) $mailbox = '{localhost:110/pop3/notls}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox); # IMAP で接続(成功) $mailbox = '{localhost:143/imap/notls}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox);
ところが、SSL/TLS を導入後 imap_open でエラーが出るようになりました。 (POP3S:995番ポート、IMAP4S:993番ポート)
# POP3S で接続(失敗) $mailbox = '{localhost:995/pop3/ssl}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox); # IMAP4S で接続(失敗) $mailbox = '{localhost:993/imap/ssl}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox);
「/novalidate-cert」を付けるだけ。。。
# POP3S で接続(成功) $mailbox = '{localhost:995/pop3/ssl/novalidate-cert}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox); # IMAP4S で接続(成功) $mailbox = '{localhost:993/imap/ssl/novalidate-cert}INBOX'; $mbox = imap_open($mailbox, $account, $password) or die('接続エラー: ' . imap_last_error()); imap_close($mbox);
デバッグ情報を表示するようにしたり、色々試した結果、最終的には PHPの公式ドキュメントにあるコメント の記述に助けられ、無事動くようになりました。
公式ドキュメントには「/novalidate-cert」オプションは、自己証明書を使っている際に必要、とあったので、Let's Encrypt を使用していた今回は関係ないと思っていたのですが、原理は分からないままなものの、このオプションを付けることで成功するようになりました。
ちなみに、Thunderbird などのメールソフトでは正常に送受信に成功しているので、証明書が間違っているということはありません。
なぜだ。。。