「問い合わせフォームから送ったのに、メールが届かない」という相談は多い。しかも厄介なことに、送信処理自体は成功していることがほとんどだ。エラーも出ないまま、どこかで消えている。
原因は大きく3つに分かれる。切り分けの順に見ていく。
そもそもサーバーから出ていないのか、出たあと捨てられたのか
最初に切り分けるべきはここ。方法は単純で、別のドメインの受信箱に送ってみる。
- 自社ドメイン宛には届かないが、Gmail には届く → 自社のメール受信側の問題
- どこにも届かない → 送信側の問題
PHP の mail() や mb_send_mail() は、サーバーが受け付けた時点で true を返す。その後に配送が失敗しても、こちらには何も返ってこない。だから「送信成功」という表示は、届いた証拠にはならない。
送信結果が false の場合も含め、失敗時は内容をログに残しておくこと。問い合わせが消えるのは、スパムを1件受け取るより遥かに損害が大きい。
原因のほとんどは「送信元アドレス」
いちばん多いのがこれ。フォームの送信処理を、次のように書いていないだろうか。
// これが原因になる
$headers = 'From: ' . $_POST['email'];
mail($to, $subject, $body, $headers);
送信者本人のアドレス(たとえば taro@gmail.com)を From に入れている。一見すると自然だが、これは「gmail.com からのメール」を名乗っていることになる。実際に送っているのは自社のサーバーなので、受け取る側から見るとなりすましそのものだ。
現在のメールサーバーは、これを次の仕組みで検出する。
| 仕組み | 何を見ているか |
|---|---|
SPF |
そのドメインのメールを、このサーバーが送ってよいか |
DKIM |
送信途中で内容が書き換えられていないか(電子署名) |
DMARC |
SPF/DKIM に失敗したメールをどう扱うか(拒否・隔離・許可) |
gmail.com の SPF に自社サーバーは登録されていないので、判定は失敗する。DMARC の設定次第では、そのまま捨てられる。エラーも通知も返らない。
正しい書き方
From は必ず自社ドメインの実在するアドレスにする。送信者のアドレスは Reply-To に入れる。こうすれば、受け取ったメールにそのまま返信すれば相手に届く。
$headers = [
'From' => 'お問い合わせ <info@example.com>', // 自社ドメイン
'Reply-To' => $email, // 送信者。返信先になる
'Content-Type' => 'text/plain; charset=UTF-8',
];
// 第5引数の -f は「封筒の差出人」。SPF はこちらを見る
mb_send_mail($to, $subject, $body, buildHeaders($headers), '-f info@example.com');
ポイントは2つ。
From(本文に表示される差出人)と、-fで指定するエンベロープ送信者は別物。SPF が見るのは後者- ヘッダに入れる値からは改行を除去する。改行を仕込まれると宛先を書き換えられる
foreach ($headers as $key => $value) {
$lines[] = $key . ': ' . str_replace(["\r", "\n"], '', $value);
}
自社ドメインの SPF を確認する
送信元を自社ドメインに直したら、そのドメインの SPF レコードにサーバーが含まれているかを確認する。
nslookup -type=txt example.com
v=spf1 で始まる行が SPF レコードだ。レンタルサーバーを使っている場合、契約時に設定済みのことが多いが、ドメインを別事業者で管理している場合は入っていないことがある。この場合はDNS側に追加する必要がある。
それでも届かないとき
ここまでやって届かないなら、受信側の問題を疑う。
- 迷惑メールフォルダに入っていないか(自分宛のフォームメールは、内容がスパムに似ているため振り分けられやすい)
- メールボックスの容量が上限に達していないか
- 受信側で転送設定が働いていて、転送先で弾かれていないか
3つ目は見落とされやすい。転送を挟むと SPF の判定が変わるため、元は正しく送れていても転送先で落ちることがある。
気づかないうちに失っている
この問題のいちばん厄介なところは、誰も気づかないことにある。問い合わせた側は「返事が来ない会社」と判断して次に行き、こちらには何も残らない。
フォームを設置したら、必ず自分で一度送って受信を確認する。そして年に一度は、同じ確認をしたほうがいい。サーバー移設やDNS変更のタイミングで、静かに壊れていることがあるためだ。