のんラボ

CakePHP3でShellでメール送信できなかった話

2019/12/17 2019/12/18 CakePHP3でShellでメール送信できなかった話

CakePHP3でShellでメール送信するときに気をつけること

こんにちは。Nonです。
今回は僕がCakePHP3でメール送信する際にハマったときのことを書こうと思います。

ちょっと重ための処理をシェルで実行した後、メール送信する処理を作った話。

ハマる前に少しだけ前提知識を書くと、ちょっと重ための処理が合ったのですが、これをユーザーに待たせるのは避けたく、バックグラウンド(シェル)で実行して、その完了通知をメールで通知しようという処理があったのです。

そのときに、メールが送信できない現象が発生しました。

Gsuiteのrelayを使用していますので、他の人はこの現象発生しないかも?

結論

config/app.phpEmail設定にclientは指定しておいたほうが吉。

copied.'EmailTransport' => [
    'default' => [
        'className' => 'Smtp',
        // The following keys are used in SMTP transports
        'host' => 'smtp-relay.gmail.com',
        'port' => 587,
        'timeout' => 30,
        // ここNULLは避ける↓
        // 'client' => null,
        // ここドメインを指定↓
        'client' => 'example.com'
        'tls' => true,
    ],
],

何故か?

/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php

copied.protected function _connect()
{
    $this->_generateSocket();
    if (!$this->_socket->connect()) {
        throw new SocketException('Unable to connect to SMTP server.');
    }
    $this->_smtpSend(null, '220');

    $config = $this->_config;

    if (isset($config['client'])) {
        $host = $config['client'];
    } elseif ($httpHost = env('HTTP_HOST')) {
        // ここ$config['client']がNULLだったら設定されたドメイン
        list($host) = explode(':', $httpHost);
    } else {
        $host = 'localhost';
    }
    ...
}

clientが存在しなければ環境変数HTTP_HOSTclient、それ以外ならlocalhostとして設定され、接続されます。

このときの環境変数HTTP_HOSTですが、諸事情により自分で設定した違うドメイン(購入していないローカルPCだけのドメイン)でした。

さらに本番環境でShellを実行すると、環境変数が強制的にLocalになってしまう始末。。。(皆さんはちゃんとプログラムで制御してください。)

まぁlocalhost.test.comで接続なんて許されませんよねw
それに仮にlocalhostで接続したとして、Gmailがlocalhostでの接続を許してくれるのでしょうか?
これは検証する必要があるかもしれません。

最後に

今回は短めでしたが、CakePHP3のソースを追わないとわからない内容だったと思います。
皆さんの力になれれば嬉しいです。

ところで

copied.'client' => 'example.com'

で設定してもうまくいくのでしょうか?私の修正後のコードはセキュリティの観点からお見せすることはできませんが、購入したサーバーに接続できるhostでした。
仮にここにlocalhost.test.comを入れた送信できないのでしょうかね?(まぁできないと思う。)

最近ちょっとした処理でフレームワークの処理を追うことになったので、こういったニッチな解決法を発見したら、今後も記事にしていきたいと思います。

その時はよしなに。

.