# インターネットメールの基礎

## メールシステムを構成する要素

### メール

まずメールそれ自体です。 メールは基本的にはテキストファイルであり、ヘッダ `(header)` と ボディに分かれています。ヘッダの書式は規格がありかなり厳密に 決められていますが、ボディにはありません。たとえば以下が生の メールの例です。

    Return-Path: <ruby-list-admin@ruby-lang.org>
    Received: from helium.ruby-lang.org (localhost [127.0.0.1])
    	by helium.ruby-lang.org (Postfix) with ESMTP
    	id 4EEF9165; Wed, 12 Dec 2001 07:05:58 +0900 (JST)
    Received: from doraemon.edit.ne.jp (doraemon.edit.ne.jp [210.141.234.1])
    	by helium.ruby-lang.org (Postfix) with ESMTP id 7AFAB126
    	for <ruby-list@ruby-lang.org>; Wed, 12 Dec 2001 07:05:57 +0900 (JST)
    Date: Wed, 12 Dec 2001 07:05:58 +0900
    Posted: Wed, 12 Dec 2001 07:14:16 +0900
    From: Minero Aoki <aamine@mx.edit.ne.jp>
    Reply-To: ruby-list@ruby-lang.org
    Subject: [ruby-list:32880] Re: RAA update
    To: ruby-list@ruby-lang.org (ruby mailing list)
    Message-Id: <20011212071416N.aamine@mx.edit.ne.jp>
    In-Reply-To: <20011210141226.DTUM11600.femail11.im.home.ne.jp@witch>
    References: <20011210141226.DTUM11600.femail11.im.home.ne.jp@witch>
    Mime-Version: 1.0
    Content-Type: Text/Plain; charset=iso-2022-jp
    Content-Transfer-Encoding: 7bit
    Precedence: bulk
    Lines: 79
    X-UIDL: b8b1b7f1d28ee02af1df6f8612b5b8c4

    あおきです。ここからボディです。
       ：
    (以下略)

ヘッダとボディは空行で区切られます。ヘッダではだいたい一行が ひとつのヘッダに相当しますが、空白で始まる行は上の行の続きです。 たとえばこのメールの `Received:` は二つとも 3 行でひとつのヘッダ行を 構成しています。各ヘッダには最初にヘッダ名があり、コロン(：)を 置いてそのあとが「ヘッダフィールド」(ヘッダの内容)です。

ヘッダにはそれぞれ役割があります。たとえば `To:` ヘッダには メールの宛先を書きます。`From:` にはメールの送り元を書きます。 `Subject:` はいわゆる題名です。`Date:` はメールを送信した日時、 `Received:` が配送記録などなど。詳しくはあとで説明します。

### メールの送受信

細かく追求すれば送信にもいろいろな方法があるのですが、普通に 生きていく限り関係しなくてはいけないのは `SMTP (Simple Mail Transfer Protocol)` だけです。これは、とあるホストから別のホストにメールを転送する ためのプロトコル (約束事の集合) です。とにかくこれを使えば メールを転送できます。`SMTP` ではメールの中身には基本的に関与 しません。少なくとも、メールの中身を変えてしまうような働き かけは行いません。

またメールには本来「受信」というものはありませんでした。 基本的にメールシステムは常時接続が基本で、メールを送ったら 即座に送り先まで `(SMTP` で) 配送されることになっていたからです。 いまで言えば携帯メールみたいなものです。

ところがそのうち常時接続でないところが出てきて、解決方法を 考えはじめました。そこで出てきた解決法のひとつが最近使ってる 「受信」なわけです。これには普通は `POP3 (Post Office Protocol version 3)` というプロトコルを使います。

`POP3` では、配送されたメールを `POP` サーバに保存しておき、それを `(PPP` でつないだパソコンとかから) リクエストされたら渡し、その あと消します。つまり本当は「送信待機」とでも言うほうがより正確 でしょう。

他の解決法としては IMAP (Internet Messsage Access Protocol) と いうプロトコルが代表格です。`POP` はメールの送信を介助するだけですが、 IMAP では普通のメールクライアントの機能の一部までがサーバに取り こまれたような感じになります。たとえば IMAP サーバ上でメールの 検索をしたり、メールボックスの分類ができたりします。携帯メール なんかは実は IMAP に類似の構造です。携帯は CPU パワーがないので、 サーバ上でメールを加工して携帯に渡しているのです。

### メールボックス

届いたメールを最終的に保存しておくところがメールボックスです。 きっとどこかで聞いたことがあるであろう `INBOX` とか「受信箱」とか 「郵便受け」がそれです。

メールボックスは、メーラ次第でいくらでも変えることができてしまう ので相当にたくさん種類があります。超有名なのだけでも UNIX mbox (さらにマイナーバージョンがいくつかある)、MH、`Maildir` なんてのが あります。

なんにしてもメールボックスはメールをとっておければいいのです。 形式については深く追求しないことにしましょう。

## メールシステムの抱える問題

メールは現在あるなかではほとんど最古参の古いシステムですから、 特有の問題が死ぬほどあります。以下いくつか挙げましょう。まず 送受信から。

- 8 ビット透過でない
- ASCII 文字以外を送ると危険
- メールの `To:` と `SMTP` の To (RCPT TO) は無関係
- メールの `From:` と `SMTP` の `From (MAIL FROM)` も無関係

メール自体について。

- ASCII 文字以外を入れるとバグるメーラが (いっぱい) ある
- ヘッダの書式が超複雑
- しかも国際化の過程でさらに複雑になった
- 某社のメーラが規格を無視したメールばっかり生成するのでもはやどうにもならないくらい複雑になった

メールボックスについて。

- 種類がありすぎてどれを使えばいいのかわからない
- 種類がありすぎて全部対応なんてできない
- 種類がありすぎて互換性に問題が (よく) 出る
- やっぱり 8 ビット透過でない

そんなわけで、`TMail` が数千行あるのにはそれなりの理由が あるのです。多少ロードが遅くても目をつぶってください。

## メールの持つ情報

メールヘッダに格納されている情報について少し詳しく解説します。 もっと詳しく内容や書式について知りたい人は RFC2822 などを見るとよいでしょう。

`To:`

  宛先。複数アドレスを格納。

`From:`

  送り主。複数アドレスを格納。 (ただし通常ひとつで複数のときは `Sender:` をつけなければいけない)

`Subject:`

  主題。メールに書いた内容を一言で凝縮したもの。 「題名」とはちょっと違う。

`Date:`

  メールを送った日時。受け取った時間でも書いた時間でもない。

`Message-Id:`

  全世界においてメールと一対一に対応する (させなければならない) 文字列。メールを作成したホストの `FQDN (`正式ホスト名) と時刻、 プロセス／スレッド `ID`、ランダム文字列などを使って作るのだが、 `PPP` 接続なパソコンだったりすると `FQDN` がないので困る。そういう ときは、危険なのを承知でプロバイダのメールサーバの `FQDN` に適当な 文字列をくっつけて使うしかないと思う。

  ちなみに `sendmail (`一番有名な `SMTP` サーバ) は勝手にメッセージ `ID` をつけてくれるので、それを期待するのもよいかもしれない。が、 `qmail` なんかはつけてくれないし、規格に正確に従うならばメーラが 付けるのが正しい。

`In-Reply-To:`

  このメール、が返信した対象のメール、のメッセージ `ID`。 この情報を使って返信関係をツリーにするとよく見る 「スレッド表示」になる。

`References:`

  このメールが返信したメール、が返信したメール、が返信したメール…… と再帰的にたどって集めたメールのメッセージ `ID` の集合。 `In-Reply-To` と同じように、メールスレッドを作るのに使える。

  基本的には関係あるメールの `ID` は全部入れるが、さすがに 多すぎるときは古いものから省略してよい。たとえば 12 個とか。

`Reply-To:`

  メールに返信するときに使うアドレス。このヘッダがある場合は 絶対に `From:` にメールを返してはいけない。

`Received:`

  配送経路情報。メールシステムのデバッグや `SPAM` の発送元の 特定とかに使える。こともある。簡単に偽造できるから信用 しすぎてはならない。

`X-*:`

  `X-` が頭についているヘッダは規格で決められたのではない。 つまり解釈は自由。有名なとこでは `X-Mailer (`メーラ名)とか。

`Mime-Version:`

  Content-* ヘッダをつけるなら必ずつけなければいけない。 いまのところ常に `"1.0"`。

  MIME とは `Multipurpose Internet Mail Extentions` の略だが いまは同じ技術がメールに関係なくいろんなところに使われている。

Content-Type:

  メールの中身がなんであるか示す。なんであるか、とは、 たとえば「プレーンテキストである」とか「`JPEG` である」とか。 俗に言うところの「MIME タイプ」。Content Type の種類に関しては 次のセクションで詳述。

Content-Disposition:

  メールの位置付け。というとわけわかんない。ありていに 言うと、マルチパートメールのときにパートが他のパートと どういう関係にあるかを示すもの。たとえば HTML とそこに 入ってる絵とか、そういうこと。やりかたは……やってほしく ないから、言わない。どうしてもやりたければ自分で調べて。

Content-Transfer-Encoding

  前述したように `SMTP` は 8 ビット透過でないので、8 ビットめが 立ってるときはなにかエンコードして送る。そういうときに このヘッダに `Base64` とか書いたりする。

## Content Type

有名な Content Type には以下のようなものがある。

- `text/plain`
- `text/html`
- `image/gif`
- `image/png`
- `image/jpeg`
- `application/octet-stream`
- `multipart/mixed` (次のセクションを参照)

ま、だいたいわかるでしょ。また `text` には `charset` という パラメータがつきもので、文字コードのエンコーディングを 指示する。もちろん `charset` とエンコーディングは別物であるのだが いったん規格で決まってしまった以上はそう簡単に変えられないのだ。 我々に関係ある `charset` 値は次のもんくらい。

- `us-ascii`
- `iso-2022-jp`
- `iso-2022-jp-2` `(iso-2022-jp` を韓国語とかにも対応させて拡張したもの)
- `euc-jp`
- `shift_jis`
- `utf-8`

普通の日本語使いならば `iso-2022-jp (JIS)` を使っておけばよい。というか そうすべき。(もちろんちゃんと `NKF.nkf('-j',str)` でボディを変換すること)

## マルチパートメール

Content-Type: multipart/* のとき、メールはマルチパートメール というのになっている。一言で言うと、メールボディの中にまたメールが 入っているのである。俗に言う「添付ファイル」はこれを使って テキストのメールと画像のメールをひとつのメールに含めているわけだ。 つまり添付とは言っても形式上ではテキストと画像は並列に並んでいる。

## 比較的マイナーな MIME 拡張

### 分割メール

ひとつのメールを複数のメールに分割して送ることができる。 このとき Content-Type: message/partial。作りかたは RFC2046 を参照。

メールがでかくなりすぎると途中のファイアウォールとかが 勝手にこれを使ってぶったぎることがあるのでときたま見かける。 しかし相手が分割メールを再生できることが保証されるならばいいが、 そうでないならそういう勝手なことをしてはいけない。送り元に エラーを返すべきである。

### 外部エンティティ

メールの本体は別のところに置いてあるもの。たとえば URL を 示したりする。Content-Type: message/external-body。作りかたは RFC2046 を参照。

どこで使ってんだろうと思っていたが、`IETF` のアナウンス ML で 使っていた。インターネットドラフトとかが出ると、ヘッダだけが メールに書いてあって `external-body` で本体を指し示している。 なかなか賢い。ていうか `IETF` が使わなかったら詐欺か。 `(IETF` はインターネットで使う規格をまとめてる団体です)