ユーザ用ツール

サイト用ツール


サイドバー

Index

はじめてのおつかい






DokuWiki整形記法


PlayGround



development:language:php:tips:mb_encode_mimeheader

mb_encode_mimeheader()の文字化けについて

2016.04.26:mb_encode_mimeheader()のマニュアルを直してもらいました にて、マニュアル修正されました。まとめの「バグ報告しよう。コミッタを頼ろう。」はその通りで、お恥ずかしい限り。

正しいバッドノウハウ(^_^;)

ネット上で検索すると良く出てくるのが「38バイト目(74 文字)で文字化けが発生する」等の記述。
たしかに、38バイト目(74 文字)で文字化けが発生云々というのは現象面からするとその通りだが、実際にはmb_encode_mimeheaderの使い方に誤りがあるために起きる。

よくある間違った使い方。(mb_convert_encoding()は不要です)

 mb_encode_mimeheader(mb_convert_encoding($subject, 'ISO-2022-JP', 'UTF-8'));

mb_encode_mimeheader は内部で mb_convert_encodingを行っているため単体で使用して大丈夫です。
ただし、ここでバッドノウハウが必要です。
mb_encode_mimeheaderに引き渡す文字列の文字コードをmb_internal_encodingと一致させてください。

mb_internal_encoding("UTF-8");
$subject = '十分に長い日本語の題名(subject)を作成しましょう、まる';
$mime_subject = mb_encode_mimeheader($subject,'ISO-2022-JP');

間違った迷信みたいなもの

  • mb_encode_mimeheader()に渡す文字列はISO-2022-JPに変換するな。
  • mb_convert_encoding()で ISO-2022-JPに変換した上で、ini_set('mbstring.internal_encoding', 'ISO-2022-JP')してmb_encode_mimeheader()
  • 38Byte以下で分割して使う(またはラッパーを作成しよう)

なぜこんな混乱が起きるのか

とりあえず、マニュアルからおかしいのを何とかしてくれ。 以下 http://jp2.php.net/manual/ から

string mb_encode_mimeheader ( string $str [, string $charset [, string $transfer_encoding [, string $linefeed = "\r\n" [, int $indent = 0 ]]]] )
str
    エンコードする文字列。 
charset
    charset は、str の文字セット名です。デフォルトは、現在の NLS 設定 (mbstring.language) によって決まります。 
    mb_internal_encoding() を同じエンコーディングに設定しておかなければなりません。

どこかで、この混乱のもととして、from-encoding を指定するパラメータがないこととしていましたが、
上記のcharsetの説明をみて target-encoding だと思う人がいるんでしょうかねぇ。
しかも、省略可となっているので、省略すると中途半端に変換がうまくいくのがうっとうしい。
どんな実装なんだろう?

mb_internal_encoding("UTF-8");
$subject = '十分に長い日本語の題名(subject)を作成しましょう、アイウエオ';
$mime_subject = mb_encode_mimeheader($subject,'ISO-2022-JP');

とした場合の結果

十分に長い日本語の題名(subject)を作成しましょう、アイウエオ

これに対して、charsetを省略すると

mb_internal_encoding("UTF-8");
$subject = '十分に長い日本語の題名(subject)を作成しましょう、アイウエオ';
$mime_subject = mb_encode_mimeheader($subject);
十分に長い日本語の題名(subject)を作成しましょう、?????

charsetは省略しないようにした方が良いですね

というわけで、charsetは正しくはこう書かれるはずでは?

charset
    charset は、変換後 の文字セット名です。デフォルトは、現在の NLS 設定 (mbstring.language) によって決まります。 
    また、strの文字コードは mb_internal_encoding() と同じエンコーディングに設定しておかなければなりません。

PR:


development/language/php/tips/mb_encode_mimeheader.txt · 最終更新: 2017/04/14 14:21 (外部編集)