CakePHP 4 で PHPMailer を使うときにちょっとハマったので動作するコードをメモしておきます。
今回はさくらインターネットのスタンダードプランでの内容ですが、違う環境でも応用できると思います。
環境
- さくらインターネット・スタンダードプラン
- CakePHP 4.1.7
- PHPMailer 公式:https://github.com/PHPMailer/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 で指定する値などは、利用するメールサーバーによって異なるので、正確な情報を得て反映してください。