- ベストアンサー
PHPメール送信時のエスケープについて
- PHPで作るメール送信フォームについて、フォームから受け取った値はエスケープする必要があります。
- メール送信フォームのサンプルでは、無条件でhtmlspecialcharsしていることが多いですが、プレーンテキストが文字化けしてしまうことがあります。
- データベースのSQLをエスケープするときには専用の関数がありますが、メール送信の場合はどの方法が適切か迷っています。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
HTMLメールのHTMLテキスト部分に出力するのであれば、htmlspecialcharsします。プレーンテキストのメールテキスト部分に出力するのであれば、そのままです。 メールヘッダ(Subject:など)に日本語などを出力する場合は、Bエンコーディングします。mb_encode_mimeheader メールヘッダのうちToやFrom等については書式があるので、その書式に従って書きます。
その他の回答 (3)
- superside0
- ベストアンサー率64% (463/719)
> 再入力画面にhtmlspecialchars_decodeした値を戻しているのですが、繰り返しても多重エスケープにはなっていませんでした。 htmlspecialchars_decodeしてから戻しているのなら、多重エスケープにはならないのです。 (htmlspecialcharssしたままで戻すと 多重エスケープさせてしまうことがありますが)
補足
訂正させてください。 × 再入力画面にhtmlspecialchars_decodeした値を戻している 〇 再入力画面にhtmlspecialcharsした値を戻している × htmlspecialchars_decodeの第4引数は指定していない 〇 htmlspecialcharsの第4引数は指定していない の間違えでした、大変申し訳ございません。 htmlspecialchars_decodeはしていないのに、多重エスケープにならないのです。 変数の値をhtmlspecialcharsしてそのまま変数に戻す、を試したところ、ちゃんと繰り返した分だけ多重エスケープされていました。 しかし、 1) フォームで入力された値をPOSTで受け取る 2) htmlspecialcharsしてinputのvalueやtextareaタグで挟んでフォームに表示 を繰り返しても、なぜか1で受け取ったPOSTの値はいつもエスケープされていないのです。(ファイルに保存して確認もしました。) 2でブラウザのソース表示で確認すると、ちゃんとエスケープされているのですが・・・ とりあえず当方の環境ではこういうことなので、 >余談ですが、確認画面→再入力→確認画面と繰り返したときに、 >多重にエスケープしてしまって で多重エスケープしてしまうことはないと思ったのですが・・・ うーん、またこんがらがってしまいました。
- superside0
- ベストアンサー率64% (463/719)
メールフォームによってさまざまな構成がありますが たとえば、 入力フォーム ↓ 確認画面(入力フォームの内容をHTMLで表示) 確認OK時の「送信」ボタン / 確認NG時の「戻る」ボタン ↑ ↓ メール送信 のように間にHTMLでの確認画面があったり、またはHTMLメールで送るのなら 「<script ~>」でクロスサイトスクリプト攻撃されたり 「&反転表示命令;反転文字列」でNGワードフィルターやスパムフィルターを かいくぐられてしまうこともありますので、HTML表示に使う前に 「& ダブルクォート シングルクォート < > 」のような HTML制御として意味のある文字のエスケープ処理は必須でしょう。 ただ、 エスケープした文字をそのままプレーンテキストとしてメール送信すると おっしゃる通り ”You&I” → ”You&I” ”<以下参考>”→”<以下参考>” ”Can't ” →”Can't” と(化けて?)表示されてしまう問題はあるので、 ・mb_send_mailにはエスケープしてない元の文字列のまま渡す ・mb_send_mailの直前で htmlspecialchars_decodeで元に戻す ・入力フォームの時点で「& " ' < >」の使用を禁止する ・日本語サイトのメールフォーム(氏名、住所、問い合わせコメント程度)なので 「& " ' < >」の使用を想定しない (エスケープされて表示されても気にしない) のいずれかになるでしょう。 余談ですが、確認画面→再入力→確認画面と繰り返したときに、 多重にエスケープしてしまって &→& →&amp;→&amp;amp; ' → \' → \\' (こちらはSQL用のエスケープ処理ですが) なんてこともありがちですので、 再入力画面に戻す文字列には気をつけたほうがよいです。
補足
回答ありがとうございます。 プレーンテキストであれば、元の文字列のまま渡してしまって問題ないんですね。 >余談ですが、確認画面→再入力→確認画面と繰り返したときに、 >多重にエスケープしてしまって 入力チェックでエラーがあった場合、再入力画面にhtmlspecialchars_decodeした値を戻しているのですが、繰り返しても多重エスケープにはなっていませんでした。(&1回のみ) htmlspecialchars_decodeの第4引数(double_encode)は指定していないし、なぜだろう・・・ もう一度よく確認してみます。
- okwavey2
- ベストアンサー率15% (251/1593)
>当方素人です。 投稿カテゴリ: [技術者向] コンピューター > プログラミング・開発 > PHP カテゴリは、技術者向ということのようですが、○○向と言うのは例えば、女子トイレは女子向トイレということですよね? 女子向トイレに入って、私は男性です。って言われているような事と同じように感じてしまうのですが、何か違うのでしょうか。
お礼
回答ありがとうございます。 プレーンテキスト部分であればそのまま出力していいんですね。 Bエンコーディング(mb_encode_mimeheader)やメールヘッダの書式については分かっていなかったので、また調べて勉強したいと思います。