Yahoo!グループでSubjectが文字化けする原因
先日Yahoo!グループ内のメーリングリストでSubjectに文字化けのあるメールが届いた。送信者は私である。私が送信して文字化けしていないメールに返信したら文字化けして届いた。(追記:サンプル)
一般的にYahoo!グループ内のメーリングリストで文字化けした場合、次の原因が考えられるらしい。
投稿に関するお知らせが文字化けして配信される
一般的な文字化けの原因には以下のようなものがあります。
- Content-Transfer-Encoding: 8bitでの送信
- HTML形式でのメッセージ投稿
- 本文中に「半角カタカナ」「機種依存文字」など電子メッセージ上で使用すべきではない文字が含まれている場合
これらの場合は、文字化けが生じることがあります。あらかじめご了承ください。
(Yahoo!グループ ヘルプ - 投稿に関するお知らせが文字化けして配信される)
どれも心当たりが無かった。問い合わせたが上記の回答が返ってくるだけで原因は分からなかった。
と、ここまで書いた後にYahoo!グループヘルプに次のように書いてあるページを見つけた。
確認されている不具合について
Yahoo!グループでは、以下の不具合が確認されています。ご了承ください。
(Yahoo!グループ ヘルプ - 確認されている不具合について)
- 投稿に関するお知らせの件名の見出しが正しく表示されない
投稿に関するお知らせの件名に日本語が含まれていると、見出しが文字化けしたり、重複して表示されてしまう場合があります。
英字の件名に変えたり、文字数を減らすことで解決する場合もあります。
既知の不具合だったことを今になって知ったのだが(追記:ここで述べている不具合とは関係ない。「件名の見出し」は「件名」のことではなく(参照)「件名の見出し」がアルファベットでも生じる)、問い合わせても原因が分からないのなら自分で考えるしかないと思って夕方から夜中までを費やして考えた(参照)ので、その結論をここに記録しておく。
早い段階で諦めかけたのだがドラザキッド(@dorathekid999)さんに【エンコードマニアックス】を教わって(参照)から大きく進展した。感謝している。
さて、ここでは文字化けを再現したメールで報告するが、元になった送信メールのSubjectの日本語部分とソースは次の通りである。
- あいうえおかきくけこさしすせそたちつてとをさせる方法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrJC0kLyQxJDMkNSQ3JDkkOyQ9GyhC?=
=?ISO-2022-JP?B?GyRCJD8kQSREJEYkSCRyJDUkOyRrSn1LIRsoQg==?=
Yahoo!グループを経由して届いたときの文字コードは次の通りである。
- あいうえおかきくけこさしすせそたちつてとをさせる方法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrJC0kLyQxJDMkNSQ3JDkkOyQ9GyhC?=
=?ISO-2022-JP?B?GyRCJD8kQSREJEYkSCRyJDUkOyRrSn1LIRsoQg==?=
変わってない。
このメールに返信した時の送信済みトレイに残ったメールのSubjectの日本語部分は次のようになっている。
- あいうえおかきくけこさしすせそたちつてとをさせる方法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrJC0bKEI=?=
=?ISO-2022-JP?B?GyRCJC8kMSQzJDUkNyQ5JDskPSQ/JEEkRCRGJEgkciQ1JDska0p9GyhC?=
=?ISO-2022-JP?B?GyRCSyEbKEI=?=
ところが、Yahoo!グループを経由すると次のように変わる。
- あいうえおかきくけこさしすせそたちつてとをさ;$kJ}?法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrJC0bKEIbJEIkLyQxJDMkNSQ3JDkkOyQ9JD8kQSREJEYkSCRyJDUk?=
=?ISO-2022-JP?B?OyRrSn0bKEIbJEJLIRsoQg==?=
「させる方法」の所が「さ;$kJ}?法」と文字化けしている。
返信ではなく転送でも文字化けする。送信済みトレイに残ったメールのSubjectの日本語部分は次のようになっている。
- あいうえおかきくけこさしすせそたちつてとをさせる方法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrGyhC?=
=?ISO-2022-JP?B?GyRCJC0kLyQxJDMkNSQ3JDkkOyQ9JD8kQSREJEYkSCRyJDUkOyRrGyhC?=
=?ISO-2022-JP?B?GyRCSn1LIRsoQg==?=
返信時と少し違うことが分かる。これは返信時には「Re:」が付くのに対して転送時は「Fwd:」が付くためだろう。最初の文字からの文字数が半角で1文字異なるので、「ISO-2022-JP」の分割位置が変わり異なる結果になる。しかし、【エンコードマニアックス】を使えば、同じ「あいうえおかきくけこさしすせそたちつてとをさせる方法」であることを確認できる。
これがYahoo!グループを経由すると次のように変わる。
- あいうえおかきくけこさしすせそたちつてとをさ;$k方法
-
=?ISO-2022-JP?B?GyRCJCIkJCQmJCgkKiQrGyhCGyRCJC0kLyQxJDMkNSQ3JDkkOyQ9JD8kQSREJEYkSCRyJDUk?=
=?ISO-2022-JP?B?OyRrGyhCGyRCSn1LIRsoQg==?=
「させる方法」の所が「さ;$k方法」と文字化けしている。
実は、最初に文字化けに気付いたメールはこちらの転送の方と同じである。Yahoo!グループではSubjectの冒頭に件名の見出し(例えば[selfmirror7777])とメッセージ番号(例えば[00001])を付けることができる。この長さが文字化けの仕方に影響している。
さて、プログラマーでもなくbase64も理解できてない私にはSubjectのコードは意味不明な暗号である。テキストエディタにコピーしてじっくりと観察して次のことが分かった。
- 「GyRC」と「GyhC」が繰り返して見られる。→4文字ずつ区切られているのか?
- 終わり「?=」と始まり「 =?ISO-2022-JP?B?」を削除したら文字化けが解消された。→文字コードには誤りが無く分割の問題か?
- 「=?ISO-2022-JP?B?OyRrGyhCGyRCSn1LIRsoQg==?=」は「;$k方法」になる。
- 「=?ISO-2022-JP?B?GyRCJDUkOyRrGyhCGyRCSn1LIRsoQg==?=」は「させる方法」になる。
- 「=?ISO-2022-JP?B?GyRCJDUkOyRrSn1LIRsoQg==?=」も「させる方法」になる。→「GyhCGyRC」は不要?
- 「=?ISO-2022-JP?B?GyRCJDUk?= =?ISO-2022-JP?B?OyRrGyhCGyRCSn1LIRsoQg==?=」は「さ;$k方法」になる。→やはり「?= =?ISO-2022-JP?B?」による分割が問題?
- 「=?ISO-2022-JP?B?GyRCJDUkOyRr?= =?ISO-2022-JP?B?GyhCGyRCSn1LIRsoQg==?=」は「させる方法」になる。→「OyRr」を前のブロックに移動しただけで文字化けが無くなったのだから、やはり分割位置の問題?
- 「=?ISO-2022-JP?B?GyRCJDUkOyRr?= =?ISO-2022-JP?B?GyRCSn1LIRsoQg==?=」も「させる方法」になる。→「GyhC」は不要?
ここで、「GyRC」と「GyhC」が文字を表しているのではなく、文字列の最初と最後に付けるものではないかと想像して、「GyRC GyhC」でググったら、【第235章 base64の基礎】というサイトを見つけた。
【第235章 base64の基礎】を見て、base64で日本語をエンコードする手順が分かった。
「GyRC」は「2バイト文字の始まりの合図」を表しているらしく、「GyhC」は「2バイト文字からASCII文字に変わる時」に現れるらしい。しかし、「GyRC」は現れるが「GyhC」が無いこともある。「GyhC」にエンコードする前のJISコード「0x1b, 0x28, 0x42」がSubjectを含む全ての文字列を2進法で表した後の「先頭から6ビットずつ切り直す」作業で一部が前の文字に組み込まれてしまうために残りの文字で別の文字列になるらしい。
【第235章 base64の基礎】を見て、「させる方法」を手動でエンコードしたくなった。その作業を経験することで、文字化けの原因が分かると思ったからである。
結論は『「OyRr」の前で区切るということは「せ」の文字を分割していることになる。』である。また『JISコードの後ろのブロックで2バイト文字の始まりの合図「GyRC」(0x1b, 0x24, 0x42) が抜けている。』という問題もある。まとめると、『Yahoo!グループでは送信されたメールのSubjectで分割されているJISコードを一度合成してから処理して再度分割するのかもしれないが、再分割の際に「GyRC」や「GyhC」を無視するなどして、分割してはいけない所で分割してしまい文字化けを発生させている。(追記:あるいは再分割せずにメールサーバに送り、76文字を超えていることでメールサーバーが機械的に分割することで不適切な所で分割されてしまって文字化けを発生させている。【参照】)』ということだろう。(追記:ただし、この文字化けはSubjectの冒頭に件名の見出し(例えば[selfmirror7777])とメッセージ番号(例えば[00001])を付ける設定の時にしか起こらないかもしれないので、その見出しを付けたりメッセージ番号を付けたりするプログラムに問題があるのかもしれない。この不具合は返信時に「件名の見出し」と「メッセージ番号」を削除してから送信することで避けられるかもしれない。どちらか一方でも残して返信すると文字化けが生じることは確認した。)
さて、手動で確認した「させる方法」のエンコードを以下に記録しておく。
- 「させる方法」のそれぞれのJISコードは「2435, 243B, 246B, 4A7D, 4B21」である。
- 1バイトずつ横1列に表示すると「24, 35, 24, 3B, 24, 6B, 4A, 7D, 4B, 21」になる。
- 2進法で表すと「00100100, 00110101, 00100100, 00111011, 00100100, 01101011, 01001010, 01111101, 01001011, 00100001」
- 2バイト文字の始まりの合図「1b,24,42」(=「00011011, 00100100, 01000010」)を前に付けて、2バイト文字からASCII文字に変わる合図「1b,28,42」(=「00011011, 00101000, 01000010」)を後ろに付ける。
- 「00011011, 00100100, 01000010, 00100100, 00110101, 00100100, 00111011, 00100100, 01101011, 01001010, 01111101, 01001011, 00100001, 00011011, 00101000, 01000010」
- 先頭から6ビットずつ切り直す。最後が「10」で足りないので「0000」を加えて「100000」にする。
- 「000110, 110010, 010001, 000010, 001001, 000011.010100, 100100, 001110, 110010, 010001, 101011, 010010, 100111, 110101, 001011, 001000, 010001, 101100, 101000, 010000, 100000」
- 各組を16進に戻すと「6, 32, 11, 2, 9, 3, 14, 24, E, 32, 11, 2B, 12, 27, 35, B, 8, 11, 2C, 28, 10, 20」
- 16進表現からは【第235章 base64の基礎】の記号表を使って、その上の2進表現からはWikipediaにある変換表を使って記号に置き換える。
- 「G, y, R, C, J, D, U, k, O, y, R, r, S, n, 1, L, I, R, s, o, Q, g」
- 4つずつ並べて「GyRC JDUk OyRr Sn1L IRso Qg==」
- 「=?ISO-2022-JP?B?」と「?=」で挟んで「=?ISO-2022-JP?B?GyRCJDUkOyRrSn1LIRsoQg==?=」
- これを、【エンコードマニアックス】で確認すると「させる方法」になる。
コメント 0