PHPmailerから、TLS対応のSMTPサーバにTLSで接続して、SMTP認証してメールを送信しようとしたら、PHPmailerがSMTPサーバへの接続でコケてエラーを吐いていた。

んで、SMTPサーバ側のpostfixのログを確認すると見慣れないエラーが出ていた。

warning: TLS library problem: 855:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:s3_pkt.c:1493:SSL alert number 48:

どうやら、TLSのコネクションを張る際のエラーのようだった。ま、何かTLSにまつわるエラー(証明書とか接続先の確認とか)だろうって、とりあえずTLSで接続する際に、

$mail = new PHPMailer();
$mail->SMTPOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    )
);

を使って、接続先の確認を省略するようにすると、無事にメールを送信できるようになったのだが、やっぱり、なんだか気持ち悪い。

ってことで、いろいろと調べてみたら、原因はPostfixに設定してあったSSL証明書に中間証明書を付けてなかったことだった。つまり、中間CAの証明書がないせいで、クライアントが持っているrootCAの証明書と、postfixにインストールしてある証明書が証明書チェーンでつながらなかったために発生していたエラーのようだった。…そういえば、先日、SSL証明書を入れ替えたときに、買ってきた証明書をそのままインストールしたような気がする…。あー、しまった。

…というわけで、postfixが読み込んでいる証明書をnginxと同じやりかたで、サーバ証明書と中間CAの証明書を1つのファイルにしてPostfixを再起動してみると、phpmailerから普通にTLSで接続してメールを投げることができた。

今回は自分でイジれるSMTPサーバだったから、証明書を入れ替え直して問題を解決したが、もし、中間CAの証明書を含んだ証明書に簡単に入れ替え直してもらえないようなMTPサーバを使わなきゃいけない場合は、前述のとおり、$mail->SMTPOptionsでpeerの確認を省略すれば送れるようにはなるけれど、一連のTLSの仕組みの重要な部分が確認できてない形で暗号化することになることは覚えておいた方がいいだろう。