こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

mail()でメール送信で、特定のメーラーの受信のみ件名が文字化け

PHPでメール配信プログラムを作っております。
配信テストを行なったのですが、特定のメーラーで件名が文字化けしてしまう現象に見舞われしてしまい、対処法を探しております。

■テストメーラー
1、OutlookExpress
2、EdMax
3、Thunderbird

■ソース(一部抜粋)
mb_language('Japanese');
mb_internal_encoding("SJIS");

//1 $subject = mb_encode_mimeheader($subject);
//2 $subject = mb_convert_encoding($subject,"JIS","SJIS");
$send_body = mb_convert_encoding($send_body,"JIS","SJIS");

$header = "From: $fronmail.\n";
$header .= "Return-path: $return\n";
$header .= "Reply-To: $fronmail.\n";
//3 $header .= "Subject: $subject\n";
$header .= "Message-ID: {$MessageID}\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
$header .= "Content-Transfer-Encoding: 7bit\n";
//4 $header .= "Content-Transfer-Encoding: base64\n";
$header .= "X-Mailer:PHP/".phpversion();

$chk_mail = mail($to_email,$subject,$send_body,$header);

■設定値
$body = $subject = "日本語テスト";
メールアドレスはプロバイダなどが発行しているもの

■現象
ソースのままだと1、2は件名は文字化けせず、3は文字化け(???{????? ※?はひし形に囲まれた?です)します。
それぞれコメントアウトを外したり切り替えたりするのですが、1、2も件名が文字化けになったりします。
3は基本的にどのコメントアウトを有効にしても文字化けのままです。

$subjectに関しては、mail関数のものが優先のようでして、試しに空にしてみたのですが、件名も空のままでした。

何故この形式を取っているかというと、半角カナを使いたいが為でして、mb_send_mailだと半角カナが使えなかったような気がしてmailを使っております。
あと、popenで直接コマンドを打つという手もありそうですが、sendmailではなくpostfixなのですがpostfixでコマンドをという手段を探した方が良いのでしょうか?
出来ればmailを使って文字化けもしない方向を希望なのですが、それが駄目なら他の手段など誘導していただければ幸いです。

宜しくお願いいたします。

投稿日時 - 2008-05-23 18:53:19

QNo.4044600

すぐに回答ほしいです

質問者が選んだベストアンサー

メールヘッダに生のJISを書くことは出来ません。mail()で送るのであれば、subjectはmime処理しないといけませんから。mb_encode_mimeheader()が必須です。

  http://jp.php.net/manual/ja/function.mb-encode-mimeheader.php

このとき、先にJISに変換すべきだったかどうだったか・・バージョンで若干違いがあった気もするので、下記のコードで試してみてください。

  $subject = mb_encode_mimeheader(mb_convert_encoding($subject,"JIS","SJIS");


(蛇足)
>半角カナを使いたいが為でして、

であれば、charset=ISO-2022-JPというのは間違ってます(ISO-2022-JPには「いわゆる半角カナ」はない)。どうしても送りたければcharset=UTF-8にしてください。

  mb_language('uni');
  mb_internal_encoding('sjis');

にしてmb_send_mail()を使えばmb_send_mail()がUTF-8に変換して適切なメールにしてくれます。ただしUTF-8非対応メーラも少なからずあるハズです。

投稿日時 - 2008-05-23 21:24:03

お礼

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

$subject = mb_encode_mimeheader(mb_convert_encoding($subject,"JIS","SJIS");

この辺りも試してはいるのですが

3、Thunderbird
短い件名で半角が入ると問題ないが、35kBぐらい以上の件名だと本文にヘッダ情報が載ってしまう

1、2に関しては最初は問題なかったが、いろんなパターンをテストしている内にもともと問題がなかったテストパターンでも件名が「=?ISO・・・」という様な形になってしまう。

ついでに携帯端末で試してみたところ、同じような結果になってしまいました。

確かmb_encode_mimeheaderにはもう一つの書き方
mb_encode_mimeheader($subject,"JIS")
というのもあったと思うのですが、こちらでも現象は似たようなものでした。

いろいろテストをしていて疑問に思ったのが、headerに設定するcharset=ISO-2022-JPがどこまで有効なのか?というところでした。
実は文字コードやこのcharsetもいろいろいじってみているのですが、時々設定と関係ない動きをすることもあるので(charsetと実際の文字コードがあっていないのにきちんと表示されたり)、もしかしたらメーラー等他の経由場所で文字コードを判別しているのかなとも思ったりします。

そして、テストを重ねるうちに、同じソースで同じテスト内容なのに結果がその都度違うという場合もあり、安定しないのも腑に落ちないところが。。。

ご教授戴きましたmb_send_mailも試しましたが、今のソースに改変では件名が文字化け「???????????」となり、本文も化けてしまっています。
ただこちらはあとでじっくり別ソースでテストを行なってみたいと思います。

投稿日時 - 2008-05-25 07:47:58

ANo.1

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

#雑感から雑談になってしまいますが(苦笑

>私もWeb歴は長いですが(技術はへぼですが)、確かに昔は半角カナはご法度
>だったんですよね。
>それが携帯でWebが出来るようになってから半角カナも使えるような仕様に
>なったりして、Webのご法度自体が変わってきたってのを感じたりします。

いいえ。wwwに関しては、昔からご法度ではありません(というか最初はキチンと規定されてなかった)。下記URL(IANA)を参照してください。ちゃんとcharset=Shift_JISで指定すれば問題ありません。この方針についてはずっと変わっていません。

  http://www.iana.org/assignments/character-sets

つまり、webで半角カナ使用不可というのはフォームなどを使う場合(プログラムやDB側の対応の問題)限定であり、表示上は何も問題がない・・というのが昔からの状態です。


ただしメールに関しては最初からISO-2022-JPが日本語標準に規定されていますので、それに従うしかありません(携帯のような閉じた世界は別にして、です)。携帯でもAU(昔からInternet標準に近い設定でした)だとメール作成時に半角カナは入力不可になっています。他キャリアはちょっと確認していませんが、多分入力可能でしょう。ガイドブックに「PCのアドレスへの送信時には半角カナや絵文字を使わないように」と書いてあった記憶がありますから。

投稿日時 - 2008-05-26 16:16:48

お礼

詳しい解説ありがとうございます。

昔、先輩方に「半角カナは使うなー!」と言われたので、原則ご法度なのかなと思っていたのですが、確かにWebの前からのパソコンでは、平仮名はともかくやっとの日本語で半角カタカナたっだんですよね。
というのはともかくとして、実はcharsetについて調べていたら、当初のISO-2022-JPの規格に半角カナは含まれて居ないという記述を見たので、そういう意味でも半角カナはNGなのかと思っておりました。

携帯の半角カナ文字はもう既に当たり前のようになっていますが、絵文字に関してだけは、外字で設定しない限りはPCでは表示できませんね。
今回のこれに対し、絵文字まで加わったらどうなるのだろうと、あまり考えたくはないですが、解決に行き詰ったときはまたこちらにお世話になるかも知れません(スミマセン・・・)。

そろそろこの件に関しては締め切らせていただきます。(運用者に怒られる前に)
本当に有難うございました。

投稿日時 - 2008-05-26 16:40:59

ANo.3

#ほとんど雑感になってしまいますが(汗

ヘッダ部(件名)に改行があるのは珍しいことではありません。RFCに従って76バイト程度で改行を入れているハズです(マニュアルのmb_encode_mimeheaderの項を参照)。またasciiと日本語を混在させると、mime後は怖ろしく長い文字列になるのが普通です。

ただ、ヘッダと本文(body)の区切りは「改行のみ」の行となっているハズなので、それ以外でヘッダ終了と検知するようではメーラ側に問題があります。実際のメールデータはどうでしたか?


ただ・・件名にまで「いわゆる半角カナ」となるとmimeでどの文字コードを指定するか悩みますね(さすがにCP932とかwindows-31というわけにはいかないかも)。またメーラがちゃんと戻せるかどうか不確実です。せめて件名は普通に書けないんでしょうか・・。UTF-8対応メーラが多くなればいいんでしょうけど、携帯まで視野にいれるとなると難儀です。

投稿日時 - 2008-05-26 12:10:56

補足

生メールメッセージは以下のようになっています。

------
[一応この前に他のヘッダ情報もありますが主要部分だけ]
Subject: =?ISO-2022-JP?B?GyRCQXc/LhsoSUM9RBskQiRKJHMkRyQ5JDEkSSEiJEkkJiRHJDckZyQm?=

=?ISO-2022-JP?B?JCshKRsoQlBhcnQy?=
Message-ID: 121176552333@exsample.com
MIME-Version: 1.0
Content-Type: text/plain; charset="Shift_JIS"
Content-Transfer-Encoding: 8bit
X-Mailer:PHP/5.2.4
Date: Mon, 26 May 2008 10:32:03 +0900 (JST)

送信テストなんですけど、どうでしょうか?Part2
送信テストなんですけど、どうでしょうか?Part2
送信テストなんですけど、どうでしょうか?Part2
------

件名は「送信テストなんですけど、どうでしょうか?Part2」です。
一応こちらを見れば何故本文にヘッダ情報が出るのかは一目瞭然なのですが、改行だけならまだしも、更に改行だけの行まであったりします。

何故このような現象が起こるのか、検索でmb_encode_mimeheaderで調べたところ、長文件名で苦労されているケースがあるようでして、もしかしたら関数の仕様の所為なのかも知れないなど思ってみました。

投稿日時 - 2008-05-26 15:13:21

お礼

またまたのご回答ありがとうございます。
一応、mb_encode_mimeheader以外の、そしてmail関数を使わないで、という方向で解決いたしました。

mb_encode_mimeheaderでエンコードされたものから改行を取り除いたり、split等で加工したりすると携帯側で不具合が出るようでして、仕方がないので手動でmb_encode_mimeheaderを行なうような形になりました。

mb_language('Japanese');
mb_internal_encoding("SJIS");
$subject = "と~っても長い長いなが~い件名デースヨヨヨヨ"; //カタカナは半角カナです
$subject = mb_convert_encoding($sunject,"JIS","auto");
$subject = base64_encoding($subject);
$subject = '=?iso-2022-jp?B?'.$subject.'?=';

この形式だと、最初に挙げましたテスト環境でも問題なく件名が表示されます。
Docomoのみ機種の仕様なのか30バイトできっちり件名をぶった切られますが、以下ヘッダ情報が本文に表示されるという現象はないみたいなので、一応目をつぶることに・・・

私もWeb歴は長いですが(技術はへぼですが)、確かに昔は半角カナはご法度だったんですよね。
それが携帯でWebが出来るようになってから半角カナも使えるような仕様になったりして、Webのご法度自体が変わってきたってのを感じたりします。
第一、ISO-2022-JPが半角カナは規格にないのに、件名ではその形式で尚且つこの書き方で表示される不思議もありますよね。(規格に加わったのでしょか・・・)

mail関数でこの形が使えるかは分かりませんが、その場合はおそらく関数上での件名の引数がどうなるのかがあると思うので、時間が出来たら検証してみたいですが・・・

いろいろヒントを戴きありがとうございました。

投稿日時 - 2008-05-26 15:31:43

ANo.2

>3、Thunderbird
>短い件名で半角が入ると問題ないが、35kBぐらい以上の件名だと本文にヘッ
>ダ情報が載ってしまう

「35kBぐらいの以上の件名」というのは普通使われないと思いますが、何かのtypoでしょうか・・。長い件名場合、mb_send_mailだと適切な「折り返し」になりますが、それ以外の作り方の場合にどうなるかは私も試していません。

いずれにしても「メーラでの見え方」も重要ですが、RFCにキチンと則ったメールデータになっているかを「生の状態のメールデータ」で確認するのが先です。メーラは可能な限りちゃんと表示しようとするので、相当にひどいものでも表示してしまいます。

>headerに設定するcharset=ISO-2022-JPがどこまで有効なのか?というところでした。

charsetは「本文」の文字コードを規定するだけです。件名などのメールヘッダに関しては意味がありません。昔「件名に日本語が使えない」理由はここにありました。今はMIMEで記述しますので件名の文字コードはMIMEの文字列で指定します。生のメールデ-タから自分でMIMEをdecodeしてみると、どうおかしいのかがわかります。

投稿日時 - 2008-05-26 09:39:35

補足

お礼を書いてからちょっと修正箇所あって修正します(汗

件名の件なんですが、メーラーやメールサーバによって状況が違ってきました・・・
状況というのは30バイト以上になると改行になっっているようですが(生のメッセージソースを見ました)、その影響で以下ヘッダ情報が本文に掲載されてしまいました。

アナログ的解決方法は30バイト以内に件名をすれば良いのですが、仮に30バイト以上でもヘッダ情報が本文に掲載されないようにするには改行をなんとかする、という感じなのでしょうか。

もう少し格闘してみます。

投稿日時 - 2008-05-26 10:46:01

お礼

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

35kBではなく35Bの記述違いでした。
申し訳ございませんでした・・・

この後もmb_send_mailで試したり、ISO-2022-JPではなくShift_JIS&Content-Transfer-Encoding: 8bitなどしてみましたが、件名での半角カナ表示が上手く行くことはありませんでした。
自分の検証の仕方にも問題があるのかも知れませんが、もしかしたら環境の問題というのもあるのかも知れません。
まだまだ勉強不足ですが、今回の件で大分勉強になりました。

最終的にはPHPの関数でのメール配信は諦め、sendmailパスをpopenして送信するところに落ち着きそうです。
これだと今のところ、PC用のテストメーラーと携帯で半角が混ざっても件名が長くなっても問題がないようです。

■ソース(細かい部分は省略)
mb_language('Japanese');
mb_internal_encoding("SJIS");

$subject = mb_convert_encoding($subject, "JIS" ,"auto");
$subject = mb_encode_mimeheader($subject);
$body = mb_convert_encoding($subject, "SJIS" ,"auto");

$mp = popen("/usr/sbin/sendmail -f $return $to", "w");
fputs($mp, "From: $from\n");
fputs($mp, "Return-path: $return\n");
fputs($mp, "Reply-To: $from.\n");
fputs($mp, "To: $to\n");
fputs($mp, "Subject: $subject\n");
fputs($mp, "Message-ID: {$MessageID}\n");
fputs($mp, "MIME-Version: 1.0\n");
fputs($mp, "Content-Type: text/plain; charset=\"Shift_JIS\"\n");
fputs($mp, "Content-Transfer-Encoding: 8bit\n");
fputs($mp, "X-Mailer:PHP/".phpversion()."\n");
fputs($mp, "\n");
fputs($mp, "$body\n");
pclose($mp);

shimixさんの仰られるとおり、今回の件で件名と本文の文字コードが完全に切り離されたものだと実感できました。(どうやらこの辺りを思い違いしてました・・・)

でもなんでmail関数を使うと件名が上手く表示できないのか・・・
関数の引数の件名が絡んでいるような違うような、という感想です。
時間があればもう少し調べてみたいと思います。

投稿日時 - 2008-05-26 10:20:57

あなたにオススメの質問