【PHP】メールシステムの文字コード

PHPで構築されたメールシステムで、UTF-8にて格納されたデータを取得して
メールデータを作成する部分があります。
以下のように件名や差出人・宛先をISO-2022-JPにエンコードするのですが、
何故か宛先名(name)のみがISO-8859-1(latin1)にエンコードされてしまいます。

//Subject
$subject = mb_convert_encoding($subject, "ISO-2022-JP", "UTF-8");
//FROM
$from_data['name'] = mb_convert_encoding($from_data['name'], "ISO-2022-JP", "UTF-8");
//TO・CC・BCC
foreach($send_data as $type => $data){
for($i=0; $i<count($data[$type]); $i++){
$send_data[$type][$i]['name'] = mb_convert_encoding($send_data[$type][$i]['name'], "ISO-2022-JP", "UTF-8");
}
}

最終的に生成されたメールのヘッダはコメントに記したとおりです。

宛先部分のみがループ処理を挟んでいますが(ToやCc、Bccで複数あり得るので…)、
そのあたりが怪しいのでしょうか?

上記ソースから心当たりがあれば、ご教示いただけると幸いです。
よろしくお願いいたします。

なお、PHPは5.2.13、データベースはMySQL5.1.50を使用しています。

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2010/09/30 15:06:44
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:rouge_2008 No.4

回答回数595ベストアンサー獲得回数351

ポイント50pt

無事に解決したという事で良かったです。

$send_data = array(
    "TO"=>array(
        0=>array(
            "name"=>"副管理人","email"=>"member@mail.example.jp"
        )
    ),
    "CC"=>array(
        0=>array(
            "name"=>"メンバー1",
            "email"=>"member001@mail.example.jp"
        ),
        1=>array(
            "name"=>"メンバー2",
            "email"=>"member002@mail.example.jp"
        ),
        2=>array(
            "name"=>"メンバー3",
            "email"=>"member003@mail.example.jp"
        )
    ),
    "BCC"=>array(
    )
);

$send_dataが上記のようになっている場合、次の処理を行うと「count($data[$type])」でカウントが0になってしまいますので、forの中が処理されません。

foreach($send_data as $type => $data){
for($i=0; $i<count($data[$type]); $i++){

「foreach($send_data as $type => $data)」としていますので、「count($send_data[$type])」あるいは「count($data)」に変更すると、正しい個数を取得できます。

ちょっとややこしいですね・・・

echo "<pre>\$data:";
print_r($data);
echo "</pre>\n";

上記のように出力して確認すると、目的の値にアクセスできているか、若干分かりやすくなると思います。

motokun44さんがコメントで指摘していますが、「mb_send_mail()」を使用する場合は、「mb_encode_mimeheader()」だけ使用すれば良いようです。

http://www.asahi-net.or.jp/~wv7y-kmr/memo/php_mbstring.html#mb_s...

※mail関数を使用する場合は、「mb_convert_encoding()」も必要です。

id:j1987

さらに情報を付加していただき、ありがとうございました。

「mb_encode_mimeheader()だけ」も試してみます。

2010/09/30 14:59:32

その他の回答3件)

id:tukihatu No.1

回答回数180ベストアンサー獲得回数32

ポイント30pt

mimeheader抜けてませんか?

//Subject
$subject = mb_convert_encoding($subject, "ISO-2022-JP", "UTF-8");
$subject = mb_encode_mimeheader($subject,"ISO-2022-JP");
id:j1987

回答ありがとうございます。

mimeheaderは上記の処理の後にまとめておこなっています。

2010/09/29 23:53:44
id:ko8820 No.2

回答回数1221ベストアンサー獲得回数69

ポイント20pt

print $send_data[$type][$i]['name'];

で出力して確認してみては?

id:j1987

回答ありがとうございます。

ご指摘のとおり、配列の中身を確認してみたところ、

ループ処理での配列要素の取得の方に問題があることが分かりました。

ISO-8859-1になっていたので、てっきりエンコードの問題かと思いましたが…。

有益なご指摘、感謝します。

2010/09/30 11:02:13
id:motokun44 No.3

回答回数42ベストアンサー獲得回数6

ポイント30pt

メールヘッダの変換には mb_encode_mimeheader() を使うのが便利です。

この関数はマルチバイト文字をiso-2022-jpに変換してbase64encodeするものですから引数は変換対象文字列だけです。

$subject = mb_encode_mimeheader($subject);

if(preg_match('/(.+)(<.+@.+>)/',$from_data['name'],$x))

$from_data['name'] = mb_encode_mimeheader($x[1]).$x[2];

To,Cc,Bccについても同様。

id:j1987

回答ありがとうございます。

mimeheaderは上記の処理の後にまとめておこなっています。

2010/09/30 11:02:16
id:rouge_2008 No.4

回答回数595ベストアンサー獲得回数351ここでベストアンサー

ポイント50pt

無事に解決したという事で良かったです。

$send_data = array(
    "TO"=>array(
        0=>array(
            "name"=>"副管理人","email"=>"member@mail.example.jp"
        )
    ),
    "CC"=>array(
        0=>array(
            "name"=>"メンバー1",
            "email"=>"member001@mail.example.jp"
        ),
        1=>array(
            "name"=>"メンバー2",
            "email"=>"member002@mail.example.jp"
        ),
        2=>array(
            "name"=>"メンバー3",
            "email"=>"member003@mail.example.jp"
        )
    ),
    "BCC"=>array(
    )
);

$send_dataが上記のようになっている場合、次の処理を行うと「count($data[$type])」でカウントが0になってしまいますので、forの中が処理されません。

foreach($send_data as $type => $data){
for($i=0; $i<count($data[$type]); $i++){

「foreach($send_data as $type => $data)」としていますので、「count($send_data[$type])」あるいは「count($data)」に変更すると、正しい個数を取得できます。

ちょっとややこしいですね・・・

echo "<pre>\$data:";
print_r($data);
echo "</pre>\n";

上記のように出力して確認すると、目的の値にアクセスできているか、若干分かりやすくなると思います。

motokun44さんがコメントで指摘していますが、「mb_send_mail()」を使用する場合は、「mb_encode_mimeheader()」だけ使用すれば良いようです。

http://www.asahi-net.or.jp/~wv7y-kmr/memo/php_mbstring.html#mb_s...

※mail関数を使用する場合は、「mb_convert_encoding()」も必要です。

id:j1987

さらに情報を付加していただき、ありがとうございました。

「mb_encode_mimeheader()だけ」も試してみます。

2010/09/30 14:59:32
  • id:j1987
    最終的に生成されたメールのヘッダです。
    差出人や件名はISO-2022-JPになっているのですが…

    From: =?ISO-2022-JP?B?GyRCJFUkQSRvJC0bKEI=?= <hoge@hoge.jp>
    Sender: hoge@hoge.jp
    To: =?ISO-8859-1?Q?=E3=83=9D=E3=82=B9=E3=83=88=E3=83=9E=E3=82=B9=E3=82=BF=E3=83=BC?=
    <hogehoge@hogehoge.jp>
    Cc: =?ISO-8859-1?Q?=E3=83=9D=E3=82=B9=E3=83=88=E3=83=9E=E3=82=B9=E3=82=BF=E3=83=BC?=
    <hogehoge@hoge.jp>
    Bcc:
    Subject: =?ISO-2022-JP?B?GyRCJV0lOSVIJV4lOSU/ITwbKEI=?=
  • id:rouge_2008
    $send_dataはどのような配列になっているのでしょう?

    $send_data = array("TO"=>array(0=>array("name"=>"副管理人","email"=>"member@mail.example.jp")),"CC"=>array(0=>array("name"=>"メンバー1","email"=>"member001@mail.example.jp"),1=>array("name"=>"メンバー2","email"=>"member002@mail.example.jp"),2=>array("name"=>"メンバー3","email"=>"member003@mail.example.jp")),"BCC"=>array());

    上記のようになっているのでしたら、「count($data[$type])」を「count($send_data[$type])」あるいは「count($data)」に変更して試してみてください。

    ※書き直して再コメントしています。
  • id:j1987
    >rouge 2008様

    $send_dataはおっしゃるとおりの内容です。
    2の方のご指摘を受け、配列の要素取得を見直したところ、
    正しく取得できればエンコードも正常になることを確認しました。

    そして、ご教示いただいた修正を実施したところ、
    正常動作いたしました。

    本当にありがとうございます。

    もしこのコメントをご覧になったら、
    是非上記内容を回答として記入してください。
  • id:tukihatu
    >mimeheaderは上記の処理の後にまとめておこなっています。
    どういう感じになっているんでしょうか…全文ないと判断できないかも。
    普通にmimeheaderが入ってないだけかなと思ったんだけど違うのかな…($subjectじゃなくてこっちでしたね…)


    //TO・CC・BCC
    foreach($send_data as $type => $data){
    for($i=0; $i<count($data[$type]); $i++){
    $send_data[$type][$i]['name'] = mb_convert_encoding($send_data[$type][$i]['name'], "ISO-2022-JP", "UTF-8");
    $send_data[$type][$i]['name'] = mb_encode_mimeheader($send_data[$type][$i]['name'] = ,"ISO-2022-JP");

    }
  • id:motokun44
    >mimeheaderは上記の処理の後にまとめておこなっています。
    mb_encode_mimeheader() を使うなら、あらかじめmb_convert_encoding()でJIS変換する必要は無いんじゃないですか。
  • id:rouge_2008
    ありがとうございます。
    ほとんど追加情報はありませんが、お言葉に甘えて回答させていただきました。
  • id:j1987
    >tukihatuさん
    mimeheaderも同様のループ処理を行っていたため、
    結果として対象の文字列に処理がかからなかったということでした。
    補足のコメントありがとうございました。

    >motokun44さん
    なるほど…。
    rouge 2008さんが挙げてくださったリンク先その他の情報を読んで、
    もっとよく勉強して構成を再考してみます。
    ご指摘ありがとうございました。
  • id:motokun44
    >rouge 2008様
    拙作フォームメール http://webmastertool.jp/f2m_php/f2mail.html では mail() を使っていますが 「mb_encode_mimeheader()だけ」で正常に動作しています。
  • id:rouge_2008
    確かにそうですね。
    「mb_internal_encoding()」を指定していれば、「mb_encode_mimeheader()」だけでも文字化けしませんでした。
    本文でエンコードが必要になる事か、あるいは、入力側の文字コードとPHPの文字コードが違う場合か何かと勘違いしていたのかもしれません。(^^;

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません