Vimとボクと、ときどき、PHP

Vim好きなエンジニア(主にPHP開発)が不定期に技術情報やネタを書いていくブログです

Home » PHPのmail関数で “Multiple or malformed newlines found in additional_header” が出た

PHPのmail関数で “Multiple or malformed newlines found in additional_header” が出た

レンタルサーバでメールフォーム有のWebサイトを運用しているのですが、いつの間にかメール送信を行う画面で

Warning: mb_send_mail(): Multiple or malformed newlines found in additional_header in /path/to/file.php on line 123

みたいなWarningが出てメールが送れなくなっていました。それへの対処法です。

原因は何?

とりあえずエラーメッセージでググってみましたが、あまり情報は無し。何とか見つけたのが、ここです。

英語はあまり得意ではないのですが、

PHP was upgraded 5.5.25-1 to 5.5.26.

このくらいなら分かります。PHPのバージョンが上がったのですね。詳しい日時は分かりませんが、比較的最近だから情報が少ないのかな?

A security risk in PHP has been fixed and additional_headers parameter is now more strictly validated.

(意訳:PHPのセキュリティリスクに関する修正が入って、パラメータ additional_headers に関してより厳しいチェックが入るようになったのさ)

だそうです。

What previously worked fine, now was causing mail() to fail, though no header injection was happening. Just had some extra newlines in additional_headers.

ここはよく分かりませんでしたが、mail()関数にはヘッダインジェクションの危険があったんだよー的なことを言ってるのかな?mb_send_mail()mail()のラッパー関数なので、mail()が修正されたからmb_send_mail()を使っているところにも影響が出たわけですね。レンタルサーバさんも、気をきかせてアップデートしてくれたんでしょうか。しかしメールが送れなくなっちまうのはキツいぜ・・・。

どうしたら直るの?

ありがたいことに、解決策まで書いてくれてます。

Solution: validate additional_headers self against header injection. These count as “multiple or malformed newlines”: \r\r, \r\0, \r\n\r\n, \n\n, \n\0

へぇ・・・ほぉ・・・ふーーーん・・・(よく分かってないやつ)

つ、つまりあれだ、エラーメッセージとあわせて雰囲気で解釈すると、「mb_send_mail()のパラメータadditional_headersに、改行が複数あるとダメになったんだよ」ってことだと思う。でもそんなところあったか?と思ってソースを見てみたら、

$headers  = "From: ".MAIL_FROM."\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"__PHPRECIPE__\"\r\n";
$headers .= "\r\n";

みたいなことやってた。なんで最後に改行を追加してるのかは、全く記憶にありません。どっかのサイトのサンプルをそのまま拝借したのかな?

とにかく、改行だけ追加してる処理を削除したら、正常にメールが送れるようになりました。

ミスらないために

今回はこれ以上の修正はしませんでしたが、上の例みたいにしてるとそのうちミスって改行を複数入れちゃいそうな予感がします。そこで、

$headers = array();
$headers[] = "From: ".MAIL_FROM;
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-Type: multipart/mixed; boundary=\"__PHPRECIPE__\"";

$additional_headers = implode("\r\n", $headers);

みたいにしたらどうかなぁと提案してみる。ちょっと実験してみたら、$additional_headersの最後に改行は不要みたいなんです。これなら改行を忘れることも、複数入れちゃうこともなくなるし、ヘッダを追加したいときも楽チン。

なんて思ってたら、mail()関数のマニュアルの中に同じ方法が書かれてた・・・マニュアルの重要性を再確認したというお話です。はい。

そういえば

mail()関数のマニュアル

additional_headers は、メールヘッダインジェクション対策を行っていません。 したがって、指定したヘッダが安全なものであり、ヘッダ以外のものを含まないようにするのはユーザー側の役目となります。 複数の改行文字を置くことでメール本文を始めたりしてはいけません。

こんなことが書いてありました。「メール本文を複数の改行文字で始めるなよ」とはありますが、「additional_headersに改行文字を複数入れるなよ」とは書かれていません。今回の修正についても記述はないです。(更新が追い付いていないだけ?)

おそらく、「additional_headersに改行文字を複数入れない」というのは、「ユーザ側の役目」の中に入っているのでしょう。いやはや、たかがメール送信と思って侮ることなかれ、しっかり勉強して理解しないといけませんね。反省。

Name of author

Name: よーすけ

Short Bio:

主にPHP開発をやってる社内PGです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です