別ページ・MHonArc で日本語メールを扱うの本 文で触れられなかった件を補足します。

MHonArc でのコード変換処理順序

日本語の文字コードは JIS, EUC-JP, SHIFT-JIS(, utf)といろいろあり、 それらの間での変換を考える必要がある上に、JIS や SHIFT-JIS だと ASCII 文 字と同じバイト列を含むことがしばしば問題となります。これだけでも頭が痛い のに、MHonArc を使う場合は更に、MIME encode/decode やメールアドレスの解 析、HTML 特殊文字の escape/unescape、URL の自動ハイパーリンク化や SPAM 対策のアドレス隠しといった他の種類の変換まで関わってきますからなおさら厄 介です。

これらのコード変換に関わる問題が発生する原因や対処法を考える上では、 MHonArc 内部で様々なコード変換がどういう順序で、どのタイミングで起きるの か、詳しく知っておくことが必要です。というわけで、ちょっと調べてみた結果 をメモとして書き残しておきます。自分でも、しばらく経ったら忘れてしまいそ うですし(笑)。

なお、以下では、MHonArc の <SUBJECTSTRIPCODE> リソースを使った Subject の書 き換えも「変換」に含めています。 別ページで説明した通り、これも文字コードなどの変換に使うことが可能な ので。

標準設定<TextEncode>, <DECODEHEADS> リソースを使わない場合)

<DECODEHEADS> リソースを使った場合、設定によっては <TextEncode> リソースと同じような効果が出ることがある ので、そのケースは後に回し、ここでは<TextEncode> リソー スも、<DECODEHEADS> リソースも使わない場合を扱います。

この場合、細かいことを無視して、コード変換などの処理の順序・タイミン グだけ大雑把に書くと以下のようになります。なお、メールヘッダ部・本文部で 処理が少し違っています。

メールヘッダ部の処理

┌────┐  ┌─────────┐  ┌────┐   ┌────┐
│ ヘッダ │  │ SUBJECTSTRIPCODE │  │アドレス│   │  MIME  │
│        ├─┤                  ├─┤        ├(1)┤        ├→
│読み込み│  │      適用        │  │  解析  │   │ decode │
└────┘  └─────────┘  └────┘   └────┘
	  ┌──────────┐   ┌─────────┐  ┌───┐
	  │ CharsetConverters  │   │ 自動リンクなどの │  │      │
	→┤    適用による      ├(2)┤                  ├─┤ 出力 │
	  │ HTML 特殊文字変換  │   │  HTML 書き換え(3)│  │      │
	  └──────────┘   └─────────┘  └───┘

(1)のタイミングでのデータが .mhonarc.db に保存されるらし い。生成される HTML で、X-Subject コメントとして埋め込まれ るのもこの時点でのデータ。したがって、これらのデータは MIME decode の、「=?ISO-2022-JP?B?ほにゃらら…」という全然読めない形。

(2)clip はこの時点で行われる模様。

(3)最後に HTML 書き換え処理が待ち受けているので、 HTML の日本語コードを JIS にしていると、文字化けが発生する

メール本文の処理

ヘッダと違って本文の処理はほとんど調べてないので、想像も交じってます が、実際の動作から考えて恐らく次のような順番でしょう。なお、ヘッダで text 以外の Content-Type が指定されていたり、 Content-Transfer-Encoding が指定されていたりすると話はもっ と厄介でしょうが、そこまでは考えていません。

┌────┐  ┌──────────┐  ┌─────────┐  ┌───┐
│  本文  │  │ CharsetConverters  │  │ 自動リンクなどの │  │      │
│        ├─┤    適用による      ├─┤                  ├─┤ 出力 │
│読み込み│  │ HTML 特殊文字変換  │  │  HTML 書き換え(3)│  │      │
└────┘  └──────────┘  └─────────┘  └───┘

つまり、<SUBJECTSTRIPCODE> と MIME decode、アドレ ス解析がないだけで、残りの順番はヘッダと同じです。ただし、本文である以上、 クリップ処理は(おそらく)行われないものと思います(ウソ書いてるかも)。 また、 添付ファイルのことは全然考えていないので、その点ご了承く ださい。

(3)HTML 書き換えが最後に待ち構えているので、 HTML の日本語コードを JIS にしていると文字化けに逢う…というのは上と同じです。

<TextEncode>を用いる場合

メールヘッダ部の処理

この場合、MIME decode 処理が真っ先に行われることに注意してください。 これよりも先の時点で、MHonArc の処理に割り込むことは(たぶん)できません。 <DECODEHEADS> リソースを使った場合も、これに準ずる処 理になることがあることに注意(以下で詳しく述べます)。

また、文字コード変換が行われる場合は、タイミングは MIME decode 処理の 直後に固定されており、これまた割り込む余地はありません。

┌────┐  ┌──────────┐  ┌─────────┐ 
│ ヘッダ │  │    MIME  decode    │  │ SUBJECTSTRIPCODE │   
│        ├─┤        及び        ├─┤                  ├→
│読み込み│  │ 文字コード変換 (4) │  │      適用        │ 
└────┘  └──────────┘  └─────────┘ 
	  ┌────┐      ┌──────────┐   
	  │アドレス│      │ CharsetConverters  │   
	→┤        ├(1)(5)┤    適用による      ├(2)→
	  │  解析  │      │ HTML 特殊文字変換  │   
	  └────┘      └──────────┘   
	  ┌─────────┐  ┌───┐
	  │ 自動リンクなどの │  │      │
	→┤                  ├─┤ 出力 │
	  │  HTML 書き換え(3)│  │      │
	  └─────────┘  └───┘

(2)の時点で clip が行われる模様、ということと、(3)HTML 書き換えが最後 に待ち構えているので、 HTML の日本語コードを JIS にしていると文字化けに逢う、ということは上と同じ。

大きく違うのは、まず(4)。関わってくるのは、 <TextEncode><DECODEHEADS> の2 つのリソースです。次の2つの場合に分けられます。

  1. <TextEncode> リソースが設定されている場合は、こ のいちばん始めの時点で文字コードがすべて指定されたコードに統一され ます(この場合、<DECODEHEADS> が指定されている かどうかはまったく無視され、どちらでも動作に影響しない)。
    そのためには、それに先だって MIME decode を行うことが必須 なので、MIME decode がすべての処理の中で一番最初に行われることにな ります。
    この場合、(1)でデータが保存されるので、.mhonarc.db に は MIME decode の「ちゃんと読める文字列」が、リソー スで指定した文字コードで保存されることになります((5)では何も 起こりません)。
  2. <TextEncode> リソースが設定されておらず、かつ <DECODEHEADS> リソースが指定されているときは、 この場合、文字コード変換は行われません。また、 <CharsetConverters>-decode- 指 定のない charset に対しては、MIME decode は (5) のタイミングまで遅らされます(上で述べた、標準設定に準じる動 作)。ただし、「どの文字コードか」を調べるため MIME 解析自体は 行わざるを得ませんが、その副作用として
    「=?ISO-2022-JP?B?…」→「=?iso-2022-jp?b?…」 のように「大文字→小文字」の変換を受けます((4)の時点で。また、「…」 部は大文字小文字の変化はしない)。
    この場合も、(1)のタイミングでのデータが .mhonarc.db に保存されるので、保存されるデータは
    -decode- 指定のある charset を持つ MIME encoded 部

    MIME decode された状態(読める文字列)で、その charset の文字コードで保存 (<TextEncode> を使った場合と違って、「リ ソースで指定した文字コード」にはならない)。

    -decode- 指定のない charset を持つ MIME encoded 部

    MIME encode された「読めない文字列」の状態のまま保存

    ということになります(iso-2022-jp に対しては -decode- 指定は論外なので、こんな分析にはあ んまり意味はありませんが)。

さて、この方式を使った場合は、上で見るようにアドレス解析が MIME decode より後になってしまいます。これは実は問題です。もし、MIME encode されているのが非 ASCII 文字だけならそれでもよいのですが、 もし From ヘッダや To ヘッダの「本名」部などで、 ASCII 文字「@」や「<」「>」などが MIME encode されて隠されていた場 合、それらの「電子メールアドレス表記上特殊な意味を持つ文字」があらわな形 で decode されてしまうため、アドレス解析が狂ってしまう可能性がありますね。

実際、 <TextEncode> 使用例として MHonArc のドキュメントに載っている「始め に全部 JIS コードに直してしまう設定」は、まさしくこれが致命的に効い てしまう場合で、実際にこの例の通りに設定しようものなら、アドレス解析 が狂うこと必至です(日本でメールヘッダの MIME encode が普及した一番 大きな理由は、この「FromTo でのアドレス解 析を狂わせる危険なしで、日本語をヘッダに含めることが可能だった」というこ となのに…)。

もちろん、これは日本語を使う場合に限った問題ではなく、どんな文字コー ドを使っていようと、潜在的には常に潜んでいる問題です。

<CharsetConverters> リソースのドキュメントでは、 -decode-」を指定する場合に当たっての注意として WARNING: If the decoded data contains the characters '<', '>', and '&', this may conflict with HTML markup.と HTML 特殊 文字との干渉については考慮されている のですが、アドレス解析との干渉 は考慮されていないようですね。

この問題は 1年ほど前にリリースさ れたバージョンで修正されたようです。最近はもう MHonArc は使ってな いので、全然気づいていませんでした。(なのでほんとに直ったかどうかも未確認です) また、もうひとつ MIME decode 処理が一番最初に行われてしまうことに起因 する問題として、「Subject などの途中で、入るべきでない空白が入ってしまう ことがある」という問題があります。

これは、詳しく見てみると、「この decode 処理がヘッダ 読み込み処理の一番入り口で、各行ごとに個別に行われる」ことに起因します。 上記「バグ報告その2」にもほぼ同様の説明がありますが、ここでは日本語で概 略を述べます。

MIME の規格では「MIME encoded 部が連続するときは、decode に当たっては その間に挟まれた“空白部”はないものとして扱う」というルールがある(おお ざっぱな表現なので、厳密ではないことにご注意ください)のですが、この“空 白部”というのは改行文字(\n)も含みます。したがって、2 行以上にわたるヘッ ダで、「1 行目の終わり」と「2 行目の始め」が共に MIME encoded 部である場 合、両者を隔てる改行文字と、2 行目の先頭の空白は全部取り除いた上で decode を行わなければいけません。

ところが今の場合、「前の行の末尾がどうだったか」「次の行の先頭がどう なるか」はまったく考慮せず、上述の通り「各行毎に個別に MIME decode が行われる」ので、この「途中の空白を全部取り除く」という処理が省 かれてしまうのですね。改行文字を取り除く処理だけはもともと入ってるのです が、残る「2 行目の先頭の空白は全部取り除いて」という要求がすっ ぽかされ、それで余分な空白が残ってしまうわけです(なお、MIME encoded 部が 同じ行内で連続する場合は、正しく途中の“空白部”を除去するよう にはなっています)。

かと言って、「行頭の空白は、直後に MIME encoded 部が続く場合はカットす る、という処理を入れれば解決」ということにはなりません。そういうことをす ると、「1 行目の最後が MIME encoded 部ではない場合、入るはずの空 白がなくなってしまう」ということになってしまいます。

繰り返し述べた通り、「各行ごとに個別に行われる」という操作が まずいのであって、この制約のもとではこの問題は解決不能です(正しく処理す るには、ヘッダを読み込む時点ではとりあえず手をつけず、改行だけ削って記録。 MIME decode はその後で、同一ヘッダ内の文字列をつなげた上で行う、というよ うにすべき。<TextEncode><DECODEHEADS> も使わない場合はそのように処理している。 また、<DECODEHEADS> を使っていても、-decode- 指定のな い charset に対しては大丈夫)。まあ、MHonArc はメールリーダー ではないのですから、「厳密な MIME 解析器」である必要はなくて、 ちょっとした空白の混入くらいは気にしないことにしてもいいと思い ますが、ただ上で引用した例のような「検索用インデックスが正しく作れない (単語を誤認識してしまうため)」という場合にはちょっと困るでしょうね。

今述べた2つの問題「アドレス解析との干渉」「空白の混入」 を防ぎ、かつ <TextEncode> や <DECODEHEAD> リソースの持つ狙い を達成するためには、ヘッダ部の処理の順番を次のようにしなければならないと考えられま す(これは、バージョン 2.6.16 までの前提で述べています。2.6.17 以降のバージョンでこうなっているかどう かは未確認。)。

┌────┐  ┌─────────┐  ┌────┐
│ ヘッダ │  │ SUBJECTSTRIPCODE │  │アドレス│
│        ├─┤                  ├─┤        ├(1)→
│読み込み│  │      適用        │  │  解析  │
└────┘  └─────────┘  └────┘
	  ┌──────────┐  ┌──────────┐   
	  │    MIME  decode    │  │ CharsetConverters  │   
	→┤        及び        ├─┤    適用による      ├(2)→
	  │   文字コード変換   │  │ HTML 特殊文字変換  │   
	  └──────────┘  └──────────┘   
	  ┌─────────┐  ┌───┐
	  │ 自動リンクなどの │  │      │
	→┤                  ├─┤ 出力 │
	  │  HTML 書き換え   │  │      │
	  └─────────┘  └───┘

(1)の時点のデータを .mhonarc.db に記録。(2) で clip 処理。

多分これ、MHonArc にだいぶ手を入れないといけないでしょうね。副作用や バグを発生させずに、うまく処理を変更するのは大変だと思います。

メール本文の処理

この場合はこんな感じ?

┌────┐  ┌──────┐  ┌──────────┐  
│  本文  │  │ 文字コード │  │ CharsetConverters  │  
│        ├─┤            ├─┤    適用による      ├→
│読み込み│  │   変換(6)  │  │ HTML 特殊文字変換  │  
└────┘  └──────┘  └──────────┘  
	  ┌─────────┐  ┌───┐
	  │ 自動リンクなどの │  │      │
	→┤                  ├─┤ 出力 │
	  │  HTML 書き換え(3)│  │      │
	  └─────────┘  └───┘

(3)HTML 書き換えが最後に待ち構えているので、 HTML の日本語コードを JIS にしていると文字化けに逢う…というのはこれまでと同じ。

(6)は、<TextEncode> リソースが指定されているのみ、 そこで指定した文字コードに変換。元の文字コードは、 Content-Type ヘッダの charset 指定がある場合は それに従い、ない場合は <DEFCHARSET> リソースの指定に 従う。<DECODEHEADS> リソースはここでは関係しない。


コンピュータ関連のページ目次へ
トップページへ
井汲 景太 <ikumikeita@home.jcom.ne.jp.NOSPAM.>(迷惑メールお断り)
最終更新日: 2012年4月20日