まおちは、エンジニアリングなるものを多少ですが、たしなんでおります。
依頼を受けて、システムの修正を行ったりもしています。
最近、増えてきたのが、迷惑メールフィルター問題です。
今年の3月にGmailが、迷惑メール対策を一気に厳しくしてから、各社一斉に厳しくなり始めました。
一括メールを送信する際に、かなりの確率で迷惑メールフィルターに阻まれてしまいます。
大規模な一括メールであれば、もうそれはメルマガですので、メルマガスタンドを契約すればすみます。
でも、メルマガ以外に、数十通、数百通レベルの一括メールが必要な場合があります。
例えば、Aと言う商品を購入した人だけに、追加の情報や注意点などを送信したい時などです。
多くのWEBシステムでは、こう言った一部の購入者に向けたメールを、一括送信できるような仕組みが搭載されています。
しかし、この仕組を利用してメールを送信すると、高確率で迷惑メールフィルターに、阻まれてメールが帰ってきてしまいます。
そこで最近増えてきた相談がこれです。
何とか迷惑メールフィルターに阻まれないように、メールを届けられないだろうか?
実は、この問題に対処するのは非常に簡単です。
メールを送信するサーバー側で、DKIMとTLSを設定すること。
そして、DNSでSPFレコードを設定すること。
なんじゃこりゃー!?
普通の人には何を言っているのかさっぱり分かりませんね。
分からなくても問題ありません。
そもそも、この方法は自社サーバーやVPSなど、特殊なサーバー環境の会社の対応策です。
一般のレンタルサーバーでは、基本的にこの対応策を全て網羅するのは不可能です。
結論を言ってしまえば、一般のレンタルサーバーに設置したWEBシステムから送信した一括メールは、迷惑メールフィルターの呪縛から逃れる事はできません。
という事で、このお話は終了です。
なんて言っていたらお仕事になりません。
ここからが、まおちのお仕事の本番です。
まず、迷惑メールフィルターに阻まれる条件を調べてみましょう。
例えば、WordPressのプラグインやEC-CubeなどのCMSは、PHPで開発されているのが一般的です。
PHPのmail関数やmb_send_mail関数を利用した一括メールは、ほぼ迷惑メールフィルターに弾かれます。
Gmailのように、そもそも迷惑メールフィルターが厳しいサービスは当然のことながら、一般的な接続プロバイダーの迷惑メールフィルターにも弾かれます。
メールが弾かれると、このようなRFC準拠ではないので、ブロックしましたと言うエラーメールが返信されてくる場合があります。
しかし、RFC準拠のフォーマットに変更して、メールを送信しても全く効果はありませんでした。
ここから導き出される1つの結論は、PHPなどを利用したWEBシステムから、送信された一括メールは、根本的にブロックされてしまうという事です。
ただし、これはfor関数などを使って、同報メールを一括で送信するときの話で、単一のメールを送信する時には、mail関数も、mb_send_mail関数も、正常にメールを届けることが出来ます。
for関数ブロック内で、sleep関数を使って、インターバルを作って送信したとしても、同報メールであれば、やはりブロックされます。
この段階で、WEBシステムからの送信は、完全に手詰まりとなるので、別の方法を考えざるを得ません。
WEBシステムが手詰まりなのであれば、ローカルアプリを使うしかありません。
そこで、同報メールアプリとして定評のある「Mail Distributor」でテストをしてみました。
このアプリは、WEBシステムから、メール送信先の一覧をCSVでエクスポートして、そのCSVをインポートして利用します。
メール送信は、WEBシステムでなく、SMTP経由で送信することになります。
このアプリを使って、100件のリストに、同じレンタルサーバーのSMTPを経由して送ってみました。
ちなみに、インターバルは3秒としています。
この実験では、全てのメールが正常に送信され、エラーメールは一件も帰ってきませんでした。
つまり、WEBシステムからの送信には非常に厳しい迷惑メールフィルターやブロックも、SMTPであれば、すんなりと通り抜けることができる事を意味します。
もし、迷惑メールフィルターやブロックにお悩みの方は、ぜひ「Mail Distributor」をお勧めします。
ただ、やはりWEBシステムからCSVをエクスポートして云々とかは、手間がかかります。
WEBシステムから、直接、送信できる方が断然便利です。
そこで、このSMTP経由のメール送信を、WEBシステム内で、再現する方法を考えてみました。
ここからはPHPのコードを使った解説となります。
興味のある方は、読み進めて下さい。
できるだけ簡単に、PHPでSMTP経由のメール送信を実現する方法はないか?
まずは、それを調べてみました。
すると、PHPMailerと言うライブラリが非常に便利であることがわかりました。
解説とサンプルを読んでみると、かなり細かく設定できます。
添付ファイルやHTMLメールの送信にも、使えそうです。
当然ですが、SMTP経由の送信も可能です。
これがサンプルです。
コメントが英語だったので全て日本語に翻訳しました。
define ("smtp_code","UTF-8"); //メールの文字コード
define ("smtp_host","smtpホスト");
define ("smtp_user","smtpユーザー名");
define ("smtp_pass","smtpパスワード");
define ("smtp_port","587"); //smtpポート
//自身の環境に合わせてPHPMailer読み込みパスを修正
require_once("PHPMailer/src/Exception.php");
require_once("PHPMailer/src/PHPMailer.php");
require_once("PHPMailer/src/SMTP.php");
//以下よりメール送信処理
//PHPMailerの使用
$mailer = new PHPMailer(true); //メール送信インスタンス生成
//Server settings
$mailer->CharSet = smpt_code; //文字コードを設定
$mailer->SMTPDebug = 0; //デバッグモードの使用
// 0:デバッグOFF
// 1:クライアントから出されるメッセージのみ出力
// 2:「1」の出力に加えてサーバからの応答も出力
// 3:「2」の出力に加えて接続時のデバッグ情報も出力
// 4:「3」の出力に加えてより多くの情報を出力
$mailer->isSMTP(); //SMTPメソッドを使用する
$mailer->Host = smpt_host; //SMTPホストの設定
$mailer->SMTPAuth = true; //SMTP-AUTHを使用
$mailer->Username = smtp_user; //SMTPユーザー名
$mailer->Password = smtp_pass; //SMTPパスワード
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;//TSLを使用
$mailer->Port = smtp_port; //ポート番号を設定
//Recipients
//Fromを設定
$mailer->setFrom("メールアドレス", mb_encode_mimeheader("名前"));
//Toを設定
$mailer->addAddress("メールアドレス", mb_encode_mimeheader("名前"));
//Replyの設定
$mailer->addReplyTo("メールアドレス", mb_encode_mimeheader("名前"));
//CCとBCCの設定
//$mailer->addCC('cc@example.com');
//$mailer->addBCC('bcc@example.com');
//Returnの設定
$mailer->Sender = "メールアドレス";
//添付ファイルの設定
//$mailer->addAttachment('/var/tmp/file.tar.gz'); //添付の例
//$mailer->addAttachment('/tmp/image.jpg', 'new.jpg'); //ファイル名の設定
//本文の設定
$mailer->isHTML(false); //HTMLメールの場合はtrue
//件名の設定
$mailer->Subject = mb_encode_mimeheader("件名");
//メールの内容の設定
$mailer->Body = "メールの内容";
//HTMLメールの場合は以下の設定が必須
//$mailer->AltBody = "HTMLが表示できない場合の代替文章";
$mailer->send(); //sendメソッドでメール送信
上記の内容をfor文で処理すれば一括メールが送信できます。
(半角のアロー演算子や比較演算子が、特殊文字扱いになるので、全角になっています、コピペする方はお気をつけ下さい)
$member = [
['aaa@aaa.jp','Mr.A'],
['bbb@bbb.jp','Mrs B'],
[……
]; //送信先の配列を用意
for($i = 0; $i < count($member); $i++){
$mail_to = $member[$i}[0]; //送信先アドレス
$mail_to_name = $member[$i][1]; //送信先の氏名
//--ここにサンプルのメール送信処理をカスタマイズして記載--//
sleep(3); //繰り返す前に3秒のインターバル
}
3秒のインターバルで問題なく動作しています。
crontabで5分に一度、最大20通のメールを送るように設定しています。
1時間で240通のメールが送れるので十分実用的です。
動作確認は、さくらレンタルサーバーのスタンダードで行っております。
クライアントさんのXserverやヘテムルでも、問題なく動作しています。
この処理をWEBシステムやCMSのメール送信の処理と置き換えれば、もう、迷惑メールフィルターにも、ブロックにも、怯える必要はなくなります。
迷惑メールフィルターやブロックに阻まれてお困りの方は、PHPMailerを導入してみては、いかがでしょうか?
PHPMailerはこちらからダウンロードできます。