PHPのsendmailで質問があります。

以下の処理(sjisで記述)において、実行結果をPCメールクライアント(outlook, becky)で受信すると、'①②③'の文字だけが'?'に文字化けしてしまいます。
なお、ISO-2022-JPではなくbase64でエンコードすると文字化けしません。
ISO-2022-JPで特定の文字が化けるのかがわかりません。よろしくご教授お願いいたします。

●処理
$subject = 'sample';
$body = "①サンプル1
②サンプル2
③サンプル3";
$new_from = 'xx@xxxxxx';
$fromname = 'mailserver';
$recipients = 'zz@zzzzzz';

require_once "Mail.php";
require_once "Mail/mimeDecode.php";

$send_subject = mb_convert_encoding($subject, 'ISO-2022-JP', auto);
$send_body = mb_convert_encoding($body, 'ISO-2022-JP', auto);

$headers['MIME-Version'] = '1.0';
$headers['Content-Type'] = 'text/plain; charset="ISO-2022-JP"';
$headers['Content-Transfer-Encoding'] = '7bit';

$headers['From'] = mb_encode_mimeheader(mb_convert_encoding($fromname,'JIS','auto')) . "<" . $new_from . ">";
$headers['To'] = $recipients;
$headers['Subject'] = $send_subject;
$headers['Sender'] = $new_from;

$mail = Mail::factory('sendmail');
$result = $mail->send($recipients, $headers, $send_body);

●PCメールクライアントでの受信結果
?サンプル1
?サンプル2
?サンプル3

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

ベストアンサー

id:zifree No.5

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

ポイント30pt

コメントを受け付けない設定になっていたため、

申し訳ありませんが再度回答させていただきます。


OutlookのISO-2022-JPは素のISO-2022-JPに加え、いくつかの機種依存文字を含んだ独自拡張をしています。

http://ja.wikipedia.org/wiki/ISO-2022-JP#ISO-2022-JP.E3.81.A8.E6...

> 「JISコード」または「ISO-2022-JP」という名前でWindows上で実際に使われているものは、

> ISO-2022-JPの非標準な拡張で、CP932 (MicrosoftによるShift JISの亜種) と同等の機種

> 依存文字を追加している場合が多い。この独自拡張を実装したアプリケーションとしては

> Internet ExplorerやOutlook Expressがある。


上記の拡張の中にJIS X 0208の丸囲み数字も含まれているため、Outlookで送信した場合は

文字化けせずに表示ができるのです。推測になりますがBecky!も同様の理由でしょう。

この文字エンコーディングはcp50220と称されることもありますが、正式な名称ではないようです。


これに対し、PHPのmb_convert_encoding()では上記のような独自拡張を

考慮していないため、丸囲み数字をISO-2022-JPにすることができません。

上の回答で「(PHPの)ISO-2022-JP」とわざわざ括弧を付けたのはそのためです。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=34417&fo...

> 例えばphpのmb_convert_encoding関数での変換では、SJIS,EUC-JP,JISは丸付き数字でも

> OK(相互に変換可能)ですが、ISO-2022-JPに変換すると?に化けます(ISO-2022-JPは

> JISとは別物の動作になります)。

id:cochoo

なるほど、丁寧な解説で勉強になりました。

JISやISO-2022-JPにおいて、一般のメールクライアントとPHPの実装には差異があるのですね。

PHPのプログラム上の問題ではないのはわかったのですが、

文字の取り扱いは十分な基礎知識が必要ですので、みなさんのご指摘を踏まえ、再度勉強したいと思います。

ありがとうございました。

# 追伸:コメント受付不可になっていました。申し訳ございません。

2009/12/29 23:55:14

その他の回答4件)

id:zifree No.1

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

ポイント18pt

http://hal456.net/qdmail/irregular_char

(PHPの)ISO-2022-JPで、機種依存文字である丸囲み数字は文字化けしてしまいます。

UTF-8であれば使用可能なので、base64(+UTF-8ですよね?)が使用できるならそちらを使いましょう。

id:cochoo

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

ただ府に落ちないのは、PCメールクライアント(outlook, becky)から

質問と同じメッセージを送ると(メールのキャッシュをみると)MIMEはISO-2022-JPなのに、

文字化けしていません。

質問のPHPプログラムとPCメールクライアントから送ったMIMEヘッダは同じで同じメッセージを送っているのに前者は文字化けして、後者は文字化けしません。

文字そのものの問題は理解しましたが、プログラム上に問題がないかもチェックしていただけると助かります。よろしくお願いいたします。

2009/12/29 20:22:27
id:horonict No.2

回答回数257ベストアンサー獲得回数51

ポイント18pt

ISO-2022-JP は JIS X 0208 (1990) の範囲の文字セットを扱います。

丸付数字は JIS X 0208 の範囲外であるため扱うことができず、文字化けします。


下表の水色の文字が JIS X 0208 の範囲外のものです。

http://charset.7jp.net/jis.html

id:cochoo

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

文字そのものの問題は理解しましたが、先の回答者への返信のとおり、

プログラムに問題があるようにも思えますので、プログラム上に問題がないかもチェックしていただけると助かります。

よろしくお願いいたします。

2009/12/29 20:24:40
id:chinjoh No.3

回答回数103ベストアンサー獲得回数5

ポイント18pt

機種依存文字ですので、クライアントによっては化けます。

Windows機では問題ないのでは?

http://q.hatena.ne.jp/answer

id:cochoo

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

機種依存文字なのですが、なぜかWindows上のBeckyやOutlookから送ると化けません。

MIMEも同じISO-2022-JPでエンコードしているようです。

●Bekeyでの送信メールのMIME

MIME-Version: 1.0

Content-Type: text/plain; charset="ISO-2022-JP"

Content-Transfer-Encoding: 7bit

なぜそうなるのかが分からないのですが、PCメールクライアントの内部で特殊な処理をやっているのでしょうか?

2009/12/29 20:29:22
id:pah00 No.4

回答回数208ベストアンサー獲得回数5

ポイント18pt

$headers['Content-Transfer-Encoding'] = '8bit';

にして見ましょう。

http://q.hatena.ne.jp/answer

id:cochoo

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

結果ですが、解決できませんでした。

メールサーバが8bitを受け付けるかどうかはレンタルサーバの仕様なのですが、

今日は非サポートにつき、確認がとれませんでした。申し訳ありません。

しかし、先の方への返信のとおり、なぜPCメールクライアントで化けないのかが腑に落ちません。

なにかお気づきの点がございましたら、コメントをお願いいたします。

2009/12/29 20:34:57
id:zifree No.5

回答回数175ベストアンサー獲得回数6ここでベストアンサー

ポイント30pt

コメントを受け付けない設定になっていたため、

申し訳ありませんが再度回答させていただきます。


OutlookのISO-2022-JPは素のISO-2022-JPに加え、いくつかの機種依存文字を含んだ独自拡張をしています。

http://ja.wikipedia.org/wiki/ISO-2022-JP#ISO-2022-JP.E3.81.A8.E6...

> 「JISコード」または「ISO-2022-JP」という名前でWindows上で実際に使われているものは、

> ISO-2022-JPの非標準な拡張で、CP932 (MicrosoftによるShift JISの亜種) と同等の機種

> 依存文字を追加している場合が多い。この独自拡張を実装したアプリケーションとしては

> Internet ExplorerやOutlook Expressがある。


上記の拡張の中にJIS X 0208の丸囲み数字も含まれているため、Outlookで送信した場合は

文字化けせずに表示ができるのです。推測になりますがBecky!も同様の理由でしょう。

この文字エンコーディングはcp50220と称されることもありますが、正式な名称ではないようです。


これに対し、PHPのmb_convert_encoding()では上記のような独自拡張を

考慮していないため、丸囲み数字をISO-2022-JPにすることができません。

上の回答で「(PHPの)ISO-2022-JP」とわざわざ括弧を付けたのはそのためです。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=34417&fo...

> 例えばphpのmb_convert_encoding関数での変換では、SJIS,EUC-JP,JISは丸付き数字でも

> OK(相互に変換可能)ですが、ISO-2022-JPに変換すると?に化けます(ISO-2022-JPは

> JISとは別物の動作になります)。

id:cochoo

なるほど、丁寧な解説で勉強になりました。

JISやISO-2022-JPにおいて、一般のメールクライアントとPHPの実装には差異があるのですね。

PHPのプログラム上の問題ではないのはわかったのですが、

文字の取り扱いは十分な基礎知識が必要ですので、みなさんのご指摘を踏まえ、再度勉強したいと思います。

ありがとうございました。

# 追伸:コメント受付不可になっていました。申し訳ございません。

2009/12/29 23:55:14
  • id:mystashes
    手遅れでしたがPHPでも5.2.1以上のバージョンならNEC特殊文字(ISO-2022-JP-MS)を正常に扱えますよ。
    PHPを5.2.1以降にしたうえで
    mb_convert_encoding($body, 'ISO-2022-JP-MS', auto);
    とすれば良いです。
    ご参考:http://d.hatena.ne.jp/t_komura/20091101/1257080705

    あとはzifreeさんのご説明どおりです。
    beckyもoutlookもNEC特殊文字を特別扱いする処理を行っています。
    上記紹介URLに ISO-2022-JP-MS 実装用のパッチへのリンクがありますので、内部処理はそちらをご覧になれば良いと思います。
    オープンソースではSylpheedのソースも参考になるかもしれません。(SylpheedもNEC特殊文字を正常に扱えます)
  • id:zifree
    なるほど、ISO-2022-JP-MSと言うのがあったんですね。

    あと一点訂正。
    > JIS X 0208の丸囲み数字
    ではなく
    > JIS X 0208の範囲外である、NEC特殊文字の丸囲み数字
    が正しいです。
    いるか賞を頂いておきながら詰めの甘い回答になってしまいました。
  • id:cochoo
    なるほど、
    ISO-2022-JP-MSというエンコもあるんですね。
    PCメーラーと携帯メーラーの双方を考えた時、
    ISO-2022-JP(文字制限あり)かBase64にするか
    悩んでましたが、PHPも日々拡張しているのですね。
    是非試してみたいと思います。
    ありがとうございました。

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

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

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

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