ネット上に溢れている情報が、古かったりいろいろで、コピペしたコードをそのままPHPのプログラムに貼って送信すると、メールが文字化けするということがよくあります。

そもそも、ネット上に溢れている間違ったサンプルコードは、mb_send_mail()関数やmb_encode_mimeheader()関数の挙動がよくわかっていないまま掲載している模様です。正しく文字エンコーディングを理解していないまま、「その時動いた」という限定的な状況を記事として掲載しているのが問題です。(その検証が、以下のPHP都市伝説のページでも述べられていました。

結論として、文字化けしたときにチェックすべきポイント:

  • (1)どの文字コードでPHPのソースコードを保存しているか?
  • (2)mbstring拡張ライブラリにどの文字コードを設定しているか?
  • (3)間違ったエンコード処理を行っていないか?(不要な文字コード変換していないか?)

基本的なメール送信のコードは、以下のとおり。以下のソースコードを、正しく、mb_internal_encoding()の設定であるUTF-8で保存することが動作条件です。

<?php
// 言語と文字エンコーディングを正しくセット
mb_language("Japanese");
mb_internal_encoding("UTF-8");
// 宛先情報をエンコード
$to_name = "宛先太郎";
$to_addr = "taro@example.com";
$to_name_enc = mb_encode_mimeheader($to_name,"ISO-2022-JP");
$to = "$to_name_enc<$to_addr>";
// 送信元情報をエンコード
$from_name = "送信元次郎";
$from_addr = "jiro@example.com";
$from_name_enc = mb_encode_mimeheader($from_name, "ISO-2022-JP");
$from = "$from_name_enc<$from_addr>";
// メールヘッダを作成
$header  = "From: $from\n";
$header .= "Reply-To: $from";
// 件名や本文をセット(ここは自動的にエンコードされる)
$subject = "メールのテスト";
$body = " こんにちは、$to_name さん。元気ですか?";
// 日本語メールの送信
$result = mb_send_mail($to, $subject, $body, $header);
if ($result) {
  echo "Success!";
} else {
  echo "Failed...";
}

これで、メールが正しく送信できたなら、受信したメールのソースコードは次のようになるはず。

To: =?ISO-2022-JP?B?GyRCMDhAaEJATzobKEI=?=<taro@example.com>
Subject: =?ISO-2022-JP?B?GyRCJWEhPCVrJE4lRiU5JUgbKEI=?=
From: =?ISO-2022-JP?B?GyRCQXc/Ljg1PCFPOhsoQg==?=<jiro@example.com>
Reply-To: =?ISO-2022-JP?B?GyRCQXc/Ljg1PCFPOhsoQg==?=<jiro@example.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

(ここに、JISコードの本文)

メールのヘッダが、ISO-2022-JPで正しくエンコードされているかどうか、受信したソースコードを見て確認できます。

また、メール送信を行うとき、データベースと連携する機会も多いと思うので、その場合、データベースから取り出した文字列のコードを意識することも重要です。