間違いだらけのメールリーダ

IIJ技術研究所 山本和彦

これまでの連載では、メールの技術的な基礎を説明してきました。今回は少し趣向を変えまして、こういった規格が必ずしも正しく実装されていないという問題についてお話ししましょう。フリーのメールリーダやベンチャーのメールリーダは実に素敵なのに、大手ベンダーのメールリーダはどうしてこうもできが悪いのでしょうか?「悪貨は良貨を駆逐する」ということにならないよう、何がよくて何が悪いのか判断できるようになりたいものです。

ああWindows

データ型

Windows では、ファイル名のサフィックス(最後の 3 文字)から格納されているデータの種類を推測し、適切なアプリケーションを呼び出すという慣習があります。これは Windows だけに通用する慣習であって、MIME にはこんな規則はありません。

MIME ではデータ型を示すためには、Content-Type: というフィールドを使うということを前回お話ししました。Windows 系のできの悪いメールリーダでは、ありもしない NAME というパラメータにファイル名を指定し、そのサフィックスから呼び出すアプリケーションを決定することがあります。

以下にこの典型例を示します。

Content-Type: Application/Octet-Stream; NAME=foo.gif
Content-Transfer-Encoding: base64

base64 で符号化された foo.gif 

お分かりのように、正しくは以下のようにする必要があります。

Content-Type: Image/Gif
Content-Transfer-Encoding: base64

base64 で符号化された foo.gif 

このように、みんなで決めた規則を守っているふりして守っていないのは、いかにも Windows 系のアプリケーションらしいと言えばらしいでしょうか。:-p

勝手に NAME というパラメータを使ってしまった理由を無理矢理(好意的に?)考えてみるとこうなります。最初に MIME が規定された RFC 1341 では、Application/Octet-Stream(つまりバイナリ・データ)とMessage/External-body(access-type が ftp と tftp) のみにNAME パラメータがありました。Application/Octet-Stream の NAME パラメータは、ファイル名を指定するContent-Disposition: フィールドの出現を睨んでRFC 1521 で削られました。

Windows 系のメールリーダでは、最初の規格にあった Application/Octet-Stream の NAME パラメータをそれ以外の Content-Type: に対しても誤用し、改定後も修正していないのではないかと思います。

NAME でデータ型を指定するのは間違いですから、このようなメールリーダで作成されたメールは、他のメールリーダでうまく取り扱えないことがしばしばあります。

受信者が取り扱えないデータ

悪名高き某メールリーダでは、特に設定を変更しない限り作成するメールがマルチパートになり、第 2 パートに HTML が添付されます。単にテキスト(つまり日本では日本語の文章)を送るために、マルチパートを利用する必要はありません。MIME に対応していないメールリーダで読むと、パートを区切る境界文字など見苦しい余分なデータがたくさん付加されるからです。

また、多くのメールリーダが取り扱えない HTML を付けるのもおかしな話です。そもそもこの HTML で記述されているデータが、本当に HTML でなければならないのかも疑問です。

他の例としては、テキストが WORD のデータとして添付されてくるメールがあります。どうして有料の WORD を相手が持っていると仮定できるのでしょう?送信者が文章を WORD で書いたからといって、メールリーダはその WORD ファイルを単純に添付してはいけません。文章のみであれば、テキストを取り出して text/plain に直す必要があります。

WORD ファイルが送られてくる件に関しては、多くの場合おそらくメールリーダに原因があるのでしょう。しかし、ユーザにも少なからず問題があります。たとえば、Excel や PowerPoint のデータをなんの断りもなしに送り付けてくる人がいます。どうして、受信者が有料のExcel や PowerPoint を持っていると仮定できるのでしょう?もしこのような特殊なデータを送りたいなら、あらかじめ相手が持っているか確かめるべきです。

巨大な PowerPoint が送られてきた場合、僕は MagicPoint を送り返して反撃してやろうかと一瞬思うこともあります。(もちろん、報復したことはありません。)自分が持っていない MagicPoint のデータが送られてきても嫌なだけでしょう?(まぁ、MagicPoint はフリーだし、テキストベースなので問題なく読めるかもしれませんが。)

この節で述べた内容は、「読んでもらえないメールを送り付けてなにが嬉しいのか?」という疑問に集約されます。インターネットの英知を思い出しましょう:「受け取るときは寛容に、送り出すときは厳密に」

ああ文字コード

charset の決めうち

はっきり言ってしまえば、MIME の charset パラメータを適切に処理できるメールリーダはほとんどありません。できるのは、おそらく SEMI と Mew ぐらいでしょう。

charset に対する典型的な間違いは、英語だけなのに日本語と決めうちして指定してしまうことです。以下に例を示します。

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

This is an English message.

確かに、ASCII は ISO-2022-JP の部分集合(ISO-2022-JP は ASCII の拡張)ですから、文字コードの視点からみると間違いではないかもしれません。しかし、MIME には最小の適切な文字コードを charset に指定するという規則があります。この例を正しく直すと以下のようになります。

Content-Type: text/plain; charset=US-ASCII

This is an English message.

最小の文字コードを選ぶのは、受信者が処理できる可能性を広げるためです。たとえば、アメリカのメールリーダは英語しか表示できないことが多いので、最初の例のようなメールが送られて来ると、英語しか書かれていないのに読めないことになります。これは実際に起こっている問題であり、しかもこのような間違いを犯す日本のメールリーダはたくさんあります。(こういうメールリーダを見付けると、その都度作者に連絡して直してもらうようにしています。しかし、某大手メーカはちっとも直してくれません。)

charset の決めうちの問題をもう 1 つ挙げておきましょう。charset は以下の例のように各パートで指定する必要があります。

Content-Type: Multipart/Mixed; boundary="simple"

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

何かお飲物はいかがですか?

--simple
Content-Type: text/plain; charset=US-ASCII

Would you like to drink? Tea or coffee?

--simple--

あるメールリーダでは、最初のパートの文字コードに引きずられて、他のパートの charset を指定してしまいます。この例では、第 2 パートの charset が ISO-2022-JP になります。これも相手が読めなくなることは自明なので、やってはいけません。

半角かな

ISO-2022-JP では、JIS X 0201 1976 のかな文字、いわゆる「半角かな」を収容できないことになっています。にもかかわらず、charset に ISO-2022-JP を指定して、「半角かな」を送り付けてくるメールリーダがたくさんあります。

Windows 系のメールリーダでこれを訂正できない最大の理由は、ファイル名に半角かなが使われているからです。つまり、ファイル名を切り貼りして本文に書くと半角かなが入力されてしまう可能性があるのです。

現在では、送信の際に半角かなを全角かなに直すように実装することが推奨されています。

quote とヘッダの符号化

RFC 2047 で定義されている符号化を用いるとヘッダに日本語を入れることができます。以下のような感じです。

From: Kazu Yamamoto (=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=)
 <kazu@iijlab.net>

対応しているメールリーダで読むと、これはめでたく

From: Kazu Yamamoto (山本和彦) <kazu@iijlab.net>

となります。

さて問題は、「"」で囲まれた日本語を符号化してしまうメールリーダがあることです。日本語を符号化した後に、わざわざ「"」で囲むといった方が正確かもしれません。以下に例を示します。

From: Kazu Yamamoto "=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?="
 <kazu@iijlab.net>

「"」とは、「囲まれた文字列を加工してはならない」という意味です。ですから、上記の例は一見「"山本和彦"」になりそうですが、単なる「"=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?="」という文字列にすぎません。まともな MIME メールリーダで読むと、日本語には変換されずこのまま表示されます。

このように「"」を誤用しているメールリーダは山のようにたくさんあります。一体どうしてわざわざ「"」で囲むのでしょうか?(どうしてこういう間違いに陥ったのか推測できますが、ここでは述べないことにします。)こんなメールリーダも早く捨ててしまいましょう。

その他

よくない引用

メールで返答するときは、必要最小限の部分を適切に引用しそれぞれの部分に返事を返す必要があります。たとえば以下のようなメールをもらったとしましょう。

To: kazu@iijlab.net
From: itojun@iijlab.net

おはようございます。

今日のミーティングは何時からでしたっけ?

あと、歌代パパはいらっしゃいますか?

itojun

このメールには以下のような返事を書くとよいでしょう。引用の部分をよーく観察して下さい。

To: itojun@iijlab.net
From: kazu@iijlab.net

> おはようございます。
はろ。

> 今日のミーティングは何時からでしたっけ?
手帳には 16:00 って書いてあるな。

> あと、歌代パパはいらっしゃいますか?
来るって言っていたような気がします。

--かず

僕が嫌だなと思うのは、メール全体を無意味に引用し最後に付ける方法です。以下にような感じです。

To: itojun@iijlab.net
From: kazu@iijlab.net

16:00 から。パパ来ます。

--かず

> To: kazu@iijlab.net
> From: itojun@iijlab.net
> 
> おはようございます。
> 
> 今日のミーティングは何時からでしたっけ?
> 
> あと、歌代パパはいらっしゃいますか?
> 
> itojun

これまでこれはユーザがおおちゃくなせいなのだろうと思っていましたが、このような方法でしか引用ができない(あるいは難しい)メールリーダがたくさんあることが分かってきました。引用はメールの基本ですから、適切な引用もできないメールリーダは捨ててしまいましょう。:-p

メールの規格を議論している際に、このような方法で引用し偉そうなことを言われると、「まともな引用もできない技術者の話は信用できない」と僕は感じてしまいます。^^;

勝手な折り返し

メールでテキストを送る場合、長い行は忌み嫌われます。規格では、1 行は行末の CRLF を除いて 998 バイト以下であることが必須、78 文字以下であることが推奨されています。

この規則に過剰反応して、ユーザが書いた長い行を勝手に折り返すメールリーダがあります。勝手に折り返されると元に戻せません。たとえば、diff を送る場合に勝手に折り返されるととっても困ります。

もし折り返すなら、MIME の符号化(Quoted-Printable)を施すべきです。

とりあえず思い付くままにメールリーダの間違いを挙げてみました。まだまだあるような気がしますが、今回はこれぐらいにとどめます。