4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CakePHP 4 で PHPMailer を利用する

Last updated at Posted at 2020-12-23

CakePHP 4 で PHPMailer を使うときにちょっとハマったので動作するコードをメモしておきます。
今回はさくらインターネットのスタンダードプランでの内容ですが、違う環境でも応用できると思います。

環境

コード

composer.json

以下を追加して composer update します。

    "require": {
        "phpmailer/phpmailer": "6.*",
    }

設定値

app/config/app_local.php に各種設定値を書きます。
パスワード以外は app.php でもいいかなと思いますが、今回は app_local.php に書いています。

    'PHPMailer' => [
        'host' => '[さくらインターネットの初期ドメイン名]',
        'port' => 587,
        'username' => '[送信用に作成したメールアドレス]',
        'password' => '[作成したメールアドレスのパスワード]',
    ],

メール送信

Controller に書いてもいいですし、Lib など作ってラッパークラスを書いてもいいと思います。
僕は後者を選択し、 app/src/Lib/Mail.php を作成しました。

まず以下を use します。

use Cake\Core\Configure;
use Cake\View\View;
use Exception;
use PHPMailer\PHPMailer\PHPMailer;

以下でメール送信します。

        try {
            $mailer = new PHPMailer(true);
            $mailer->CharSet = 'UTF-8';

            // 設定
            $mailer->isSMTP();
            $mailer->Host = Configure::read("PHPMailer.host");
            $mailer->Port = Configure::read("PHPMailer.port");
            $mailer->SMTPAuth = true;  // SMTP authentication の有効化
            $mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;  // TLS で暗号化

            // 認証情報
            $mailer->Username = Configure::read("PHPMailer.username");
            $mailer->Password = Configure::read("PHPMailer.password");

            // from-to
            $mailer->setFrom($fromEmail, $fromName);
            $mailer->addAddress($toEmail);

            // 送信内容
            $mailer->isHTML($mimeType == 'text/html');
            $mailer->Subject = $signature . $subject;
            $mailer->Body = $content;  // あらかじめ template から展開

            return $mailer->send();
        } catch (Exception $e) {
            echo "Message could not be sent. Mailer Error: {$mailer->ErrorInfo}";
        }

        return false;

テンプレート指定と展開

body はあらかじめ template を展開した文字列を渡しました。
一例ですが、実際に動いている実装例です。

use Cake\View\View;

    /**
     * メール送信templateの展開
     *
     * template ファイルパス:app/templates/email
     *
     * @param string $templateName メールテンプレートファイル名
     * @param array $options メール送信に必要な情報配列
     *
     * @return string メールテンプレートを展開した文字列
     */
    private function expansionEmailTemplate(string $templateName, array $options = []): string
    {
        $view = new View();
        foreach ($options as $key => $value) {
            $view->set($key, $value);
        }

        return $view->render('email/' . $templateName, false);
    }

デバッグ方法

send する前のどこでもいいので、以下を追加することで、画面でデバッグできます。

use PHPMailer\PHPMailer\SMTP;

$mailer->SMTPDebug = SMTP::DEBUG_SERVER;

Failed to connect to server

ポート番号を間違えている場合など、何らかの理由で connection 確立に失敗した場合に出るエラーです。
例えば、TLS を指定しているのにポート番号が 25 だと失敗します。

2020-12-23 09:15:59 SMTP ERROR: Failed to connect to server: Connection timed out (110)
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

メール送信に成功するデバッグ例

connection 確立から切断までの流れをデバッグできます。
僕の場合は認証がうまくいかず、ポート番号や TLS 暗号化設定など確認しながら実施しました。

2020-12-23 09:06:40 SERVER -> CLIENT: 220 www****.sakura.ne.jp ESMTP Sendmail 8.15.2/8.15.2; Wed, 23 Dec 2020 18:06:40 +0900 (JST)
2020-12-23 09:06:40 CLIENT -> SERVER: EHLO localhost.localdomain
2020-12-23 09:06:40 SERVER -> CLIENT: 250-www****.sakura.ne.jp Hello ****.ne.jp [ip address], p...
2020-12-23 09:06:40 CLIENT -> SERVER: STARTTLS
2020-12-23 09:06:40 SERVER -> CLIENT: 220 2.0.0 Ready to start TLS
2020-12-23 09:06:40 CLIENT -> SERVER: EHLO localhost.localdomain
2020-12-23 09:06:40 SERVER -> CLIENT: 250-www****.sakura.ne.jp Hello ....
2020-12-23 09:06:40 CLIENT -> SERVER: AUTH CRAM-MD5
2020-12-23 09:06:40 SERVER -> CLIENT: 334 ...
2020-12-23 09:06:40 CLIENT -> SERVER: [credentials hidden]
2020-12-23 09:06:40 SERVER -> CLIENT: 235 2.0.0 OK Authenticated
2020-12-23 09:06:40 CLIENT -> SERVER: MAIL FROM:<no-reply@example.com>
2020-12-23 09:06:40 SERVER -> CLIENT: 250 2.1.0 <no-reply@example.com>... Sender ok
2020-12-23 09:06:40 CLIENT -> SERVER: RCPT TO:<mamy1326@example.jp>
2020-12-23 09:06:40 SERVER -> CLIENT: 250 2.1.5 <mamy1326@example.jp>... Recipient ok
2020-12-23 09:06:40 CLIENT -> SERVER: DATA
2020-12-23 09:06:40 SERVER -> CLIENT: 354 Enter mail, end with "." on a line by itself
2020-12-23 09:06:40 CLIENT -> SERVER: Date: Wed, 23 Dec 2020 18:06:39 +0900
2020-12-23 09:06:40 CLIENT -> SERVER: To: mamy1326@example.jp
2020-12-23 09:06:40 CLIENT -> SERVER: From: =?UTF-8?B....==?= <no-reply@example.com>
2020-12-23 09:06:40 CLIENT -> SERVER: Subject: =?UTF-8?....?=
2020-12-23 09:06:40 CLIENT -> SERVER: =?UTF-8?....?=
2020-12-23 09:06:40 CLIENT -> SERVER: Message-ID: <....@localhost.localdomain>
2020-12-23 09:06:40 CLIENT -> SERVER: X-Mailer: PHPMailer 6.2.0 (https://github.com/PHPMailer/PHPMailer)
2020-12-23 09:06:40 CLIENT -> SERVER: MIME-Version: 1.0
2020-12-23 09:06:40 CLIENT -> SERVER: Content-Type: text/plain; charset=UTF-8
2020-12-23 09:06:40 CLIENT -> SERVER: Content-Transfer-Encoding: 8bit
2020-12-23 09:06:40 CLIENT -> SERVER:
2020-12-23 09:06:40 CLIENT -> SERVER: [メール本文が表示されます]
2020-12-23 09:06:40 CLIENT -> SERVER:
2020-12-23 09:06:40 CLIENT -> SERVER: .
2020-12-23 09:06:40 SERVER -> CLIENT: 250 2.0.0 0BN96eLQ033862 Message accepted for delivery
2020-12-23 09:06:40 CLIENT -> SERVER: QUIT
2020-12-23 09:06:40 SERVER -> CLIENT: 221 2.0.0 www****.sakura.ne.jp closing connection

備考

各種設定値や PHPMailer で指定する値などは、利用するメールサーバーによって異なるので、正確な情報を得て反映してください。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?