どうもこんにちは、カフーブログのタカフです。
先日、本ブログのサーバーをエックスサーバーにお引っ越ししてみたのですが、メール送信しても何故かGmailにだけ届かない問題が発生して、sendmail以外の送信方法以外も持っておくべきだなと思い、メール送信にSMTP方式を取り入れることにしました。
一般的なレンタルサーバーは共用サーバーなので、色々なユーザーがいて中には悪質なユーザーが迷惑メールを送り続けてそのサーバーのIPアドレス自体がブロックされている可能性もあるので、
もはやレンタルサーバーからのメール送信には依存しない構成の方がいいのかもしれません。
本記事はこのブログ(WordPress)のメールをSMTP方式で送るようにする内容ですが、一般的なPHPシステムでも使える内容だと思うので今からSMTP方式でメール送信を実装しようとしている人にお役に立てるかと思います。
追記:その後エックスサーバーのメール届かない問題は時間をおいたら何故か解決しました。
概要
本ブログでは、WordPressサイトでありながら独自処理も加えたりしていてメール送信の処理には
3通りの方法がありました。
- WordPressプラグインのContact Form 7からのメール送信(wp_mail関数使用)
- 独自バッチ処理からの直接メール送信(mb_send_mail関数使用)
- エラー発生時のmonologのNativeMailerHandlerメール送信(mail関数使用)
こんな感じです。
冒頭で一般的なPHPシステムにも使える内容と書いたのはこの3通りの方法が大体のPHPシステムも使われるのではないかと思っての事です。
要は、この3通りのメール送信をSMTP方式にすればいいわけですね💁♂️
SMTP送信情報を準備する
SMTP送信するにはSMTP送信情報が必要になるのでまずはそれを準備します。
GmailでSMTP送信の準備をする場合
GmailはありがたいことにSMTP送信を使う事が出来ます。
なのでちょっとしたWebサイトで外部からメール送信したい時にはすごい便利なんですよね。ローカル開発環境にも使えます👍
GmailでSMTP送信するにはGmailでのSMTP送信情報を発行しますが、そのGmailアカウントにおいて二段階認証を有効にしているかどうかによって方法が違います。
- 二段階認証を有効にしている場合→アプリパスワードを発行する
- 二段階認証を有効にしていない場合→安全性の低いアプリの許可をオンにする
となっています。
当然ですが、二段階認証を有効にしてアプリパスワードを発行する方法を推奨されています。
二段階認証を有効にしている場合
二段階認証を有効にしている場合はアプリパスワードを発行しますが、その方法はGoogleのサイトにも記載されています。
メール送信に使うGmailアカウントの「Googleアカウント」のページに行きます。
「セキュリティ」を押下します
「アプリパスワード」の箇所を押下します。
次にアプリを選択とデバイスを選択のところで後から何のパスワードかわかるような名前を付けます。
僕の場合はこのブログ用に必要なのでサイト名「カフーブログ」で作ってますね↓
次の画面でパスワードが発行されますのでそれをコピーしておきます。
最終的には以下のSMTP情報となります。
SMTPホスト:smtp.gmail.com
SMTPポート:587
SMTPユーザー名:xxxxxxxx@gmail.com(あなたのGmailアカウント)
SMTPパスワード:xyzxyzxyzxyz(今発行したパスワード)
これをSMTP送信処理で使います。
二段階認証を有効にしていない場合
二段階認証を有効にしていない場合は「安全性の低いアプリのアクセス」を有効にします。
Googleの以下のページに行きます。
https://myaccount.google.com/lesssecureapps
Googleアカウントでログインしてこのページで有効にします。
あとはこのGoogleアカウントでログインしている情報がSMTP情報となります。
SMTPホスト:smtp.gmail.com
SMTPポート:587
SMTPユーザー名:xxxxxxxx@gmail.com(あなたのGmailアカウント)
SMTPパスワード:abcabcabcabc(あなたのGmailアカウントのパスワード)
ということでアカウントと同じパスワードを使うのでリスクがありますよね。
サーバー側にも格納しておきたくないわけです。
なので通常は上記の二段階認証を有効にしている場合の方法を使います。
メール送信処理をSMTP方式にする
SMTP送信情報を取得したらあとはPHPのメール送信処理の箇所をそれぞれSMTP方式に変えていくだけです。
Contact Form 7のメール送信をSMTPにする
本サイトではWordPressであり、お問い合わせフォームのContact Form 7を使っています。
Contact Form 7では最終的にWordPressの標準関数であるwp_mail関数を使っていますが、wp_mail関数の中身を見るとPHPMailerをインスタンス化していてそこにフックがあるので、
WordPressのフック処理でSMTP方式に変更します。
Qiitaの記事を参考にしました。テーマのfunctions.php
に以下を記述します。
add_action("phpmailer_init", function ($phpmailer) {
$phpmailer->isSMTP(); //SMTP有効設定
$phpmailer->Host = SMTP_HOST; //メールサーバーのホスト名
$phpmailer->SMTPAuth = true; //SMTP認証の有無(true OR false)
$phpmailer->Port = SMTP_PORT; //SMTPポート番号(ssl:465 tls:587)
$phpmailer->Username = SMTP_USERNAME; //ユーザー名
$phpmailer->Password = SMTP_PASSWORD; //パスワード
$phpmailer->SMTPSecure = "tls"; //SMTP暗号化方式(ssl OR tls)
$phpmailer->From = "admin@kahoo.blog"; //送信者メールアドレス(Gmailの場合は反映されない)
});
SMTP_xxxxの所は別途defineで定義しておくと良いです。
これだけでContact Form 7のメール送信がSMTP方式になります。
独自処理のメール送信をSMTPにする
一番多いのがこのパターンですかね。PHPから独自処理でmail関数やmb_send_mail関数を叩いているパターンです。
大抵はメール送信処理を関数化していると思うので、そこをライブラリ使ってSMTP方式で送信します。
PHPのメールライブラリはPHPMailerかSwiftMailerの2強だと思いますが、今Packagist見たらSwiftMailerの方がDL数多かったのでSwiftMailerを採用します。
多くの人に使われている=安定している技術理論です。
ライブラリはcomposerでインストールします。
$ composer require swiftmailer/swiftmailer
あとはautoload.phpを読み込んで処理書くだけです。
<?php
require_once "/path/to/your/vendor/autoload.php";
// SMTP方式のメール送信関数
function send_mail($mailto, $subject, $body) {
// SMTPの送信設定
$transport = (new Swift_SmtpTransport(SMTP_HOST, SMTP_PORT, 'tls'))
->setUsername(SMTP_USERNAME)
->setPassword(SMTP_PASSWORD);
// Swiftメーラーオブジェクト
$mailer = new Swift_Mailer($transport);
// メッセージ作成
$message = (new Swift_Message($subject))
->setFrom(['no-reply@kahoo.blog' => 'カフーブログ'])
->setTo([$mailto])
->setBody($body);
// メッセージ送信
if (!$mailer->send($message)) {
error_log('smtp send mail fail.');
}
}
簡単ですね。
PHPMailerだとしても同じようものかと思います。
monologのメール送信をSMTPにする
PHPのロガーといえばmonologが有名ですね。
monologもエラー発生時にだけメール送るなどがよくやるパターンで、通常はメール送信ハンドラーとしてNativeMailerHandler
を使ったりしますが、これは内部でmail関数を叩いているのでこのハンドラーを変えます。
幸運にもSwiftMailerHandler
というSMTP送信出来るハンドラーがあるのでそれを使えばOKです。
monologのハンドラー追加処理のところに以下のように記述します。
use Monolog\Logger;
use Monolog\Handler\SwiftMailerHandler;
$log = new Logger("ログネーム");
$transport = (new Swift_SmtpTransport(SMTP_HOST, SMTP_PORT, 'tls'))
->setUsername(SMTP_USERNAME)
->setPassword(SMTP_PASSWORD);
$mailer = new Swift_Mailer($transport);
$message = (new Swift_Message($subject))
->setFrom(['no-reply@kahoo.blog' => 'カフーブログ:エラー']) // GmailのSMTPの場合fromアドレスは設定されない・・・
->setTo(['[送信先メールアドレス]']);
$log->pushHandler(new SwiftMailerHandler($mailer, $message, Logger::ERROR));
$log->error("エラーだよ!");
結局は上記と一緒でSwiftMailerオブジェクトを渡しているだけですね😅
このようにハンドラー追加しておけば、errorでログ残すと同時にメールを送ってくれます。
PHPフレームワーク(CodeIgniter)のメール送信をSMTPにする
PHPフレームワークでのメール送信もよくあるパターンですね。
大抵はフレームワーク側にSMTP方式に変更出来るようになっているのでそれを利用します。
CodeIgniterだったら以下のページを参考にSMTP情報をセットします。
https://codeigniter.jp/user_guide/3/libraries/email.html#id5
Laravelでしたら以下のページが参考になるかと思います。
https://qiita.com/KZ-taran/items/ffa60ac6353bc4dcc759
.envファイルにSMTP情報書いていつものartisanコマンドですかね。
まとめ
いかがでしたでしょうか。
PHPのメール送信って結構厄介だったりしますが、SMTP方式のメール送信も技術として蓄えておくといざという時に役立つかと思います。
現場からは以上です!