メールデータの構造

メールデータの構造について調べたのでまとめてみます。

メールは全てただのテキストデータ

メールデータを理解する上で、最も重要なのは以下の1文です。以下で書かれている「テキスト」とは、ASCIIコード*1のことです。

インターネットメールは、もともとテキストベースのメールシステムであった。つまり、テキストしか送れないシステムである。

MIME(Multipurpose Internet Mail Extensions)〜前編:インターネット・プロトコル詳説(3) - @IT


でも写真やExcelファイルも添付できますよね?どういうことでしょうか?それは、以下の通りです。

あらゆるデータをテキスト(正確には、英語圏の人間にとってのテキスト)に変換して送受信しようとするのが、インターネットメールの根本的な考え方である。

MIME(Multipurpose Internet Mail Extensions)〜前編:インターネット・プロトコル詳説(3) - @IT


つまり、一通のメールは、件名も、本文も、添付ファイルも、一枚のテキストファイルとして扱っており、具体的には以下のようにまとめることができます。

  • メールで送信可能なのは、(7ビットの)ASCIIコードのみ
  • 以下のような7ビットで表現できないデータは、7ビットに(無理やり)変換して送信
    • 写真
    • Word,Excelなど
    • 英語圏以外の言語(日本語など)

参考:マルチパートメールが作られるようす

メールは「ヘッダ」と「ボディ」で構成されている

メールは以下のように、送信情報(宛先など)として「ヘッダー」があり、区切りとして「空行(CRLF)」の後に、実際のメッセージ「ボディ」というレイアウトになっています。

  1. ヘッダー
  2. 空行(CRLF)
  3. ボディ
ヘッダー

ヘッダーは、標準仕様/非標準仕様*2を含めると、かなり多くの種類があり複雑な仕様ですが、主なものを押さえておけば大抵は問題ないので、以下の項目は覚えておくと良いと思います。

  • To :宛先
  • From :差出人
  • Subject :メール件名
ボディー

ボディについては、まとめれば以下の2つしかありません。もちろん添付可能なファイルの種類はたくさんありますが。

  • 本文
  • 添付ファイル

メールデータの中身を見てみる

添付ファイルがある場合と無い場合で、メールの実際の中身を確認してみます。ここでは、特にMIMEや、Content-Typeの部分に着目して記述しています。


ケース1.テキストだけ(添付ファイル無し)のメール


下記のようなメールは、シングルパートメールと呼ばれます。Content-Typeに「text/plain;」とある通り、本文がテキスト情報だけ(添付ファイルが無い)ことが分かります。
さらにボディ部を見てみると、ヘッダーにも「charset="iso-2022-jp"」とある通り、本文の(日本語)テキストがiso-2022-jp*3エンコードされています。これは日本語を利用する場合の標準的なエンコード方法です。

メールヘッダー
From: test@example.ne.jp
To: sample@example.ne.jp
Subject: =?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit

空行(CRLF)

メールボディ
[(エスケープ文字)]$B%7%s%0%k%Q!<%H%a!<%k$N%\%G%#It$G$9!#[(エスケープ文字)](B

ケース2.画像が添付されたメール


下記のようなメールは、マルチパートメールと呼ばれ、先ほどと異なり、Content-Typeが「multipart/mixed;」となっています。
これは、「添付ファイルがあるので、ボディ部が複数のパートに分かれていますよ」という意味で、その後に記載されている「boundary="-----=_NextPart_11369_60974_45043"」が各パートの境界を示しています。


そして、マルチパートメールの場合、各パート毎にヘッダーが付与されており、以下のような情報が記載されています。

メールヘッダー
From: test@example.ne.jp
To: sample@example.ne.jp
Subject: =?iso-2022-jp?B?GyRCSiM/dCRORTpJVSVVJSElJCVrGyhC?=
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="-----=_NextPart_11369_60974_45043"

空行(CRLF)

メールボディ(1パート目)
 -------=_NextPart_11369_60974_45043
Content-Type: text/plain; charset="iso-2022-jp" ←本文テキストを表しています。
Content-Transfer-Encoding: 7bit

空行(CRLF)

メールボディ(2パート目)
 -------=_NextPart_11369_60974_45043
Content-Type: image/jpeg; name="=?iso-2022-jp?B?GyRCJVUlISUkJWsbKEIuanBn?=" JPEG画像を表しています。
Content-Transfer-Encoding: base64 BASE64形式でエンコードされています。
Content-Disposition: attachment; filename="=?iso-2022-jp?B?GyRCJVUlISUkJWsbKEIuanBn?=" ←「attachment」は添付ファイルということです。

空行(CRLF)

メールボディ(3パート目)
 -------=_NextPart_11369_60974_45043
Content-Type: image/gif; name="=?iso-2022-jp?B?GyRCJCokZCQ5JF8bKEIuZ2lm?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="=?iso-2022-jp?B?GyRCJCokZCQ5JF8bKEIuZ2lm?="

 -------=_NextPart_11369_60974_45043-- ←「--」で終わる区切り文字は、マルチパートの全体の終了を意味します。


改めて、ちゃんと見てみると、メールって結構複雑なデータ構造ですね。でも一度分かってしまえば、特に難しく感じなくなると思います。

*1:8ビット中の下位7ビットまでしか使用していないため、「7ビットコード」とも呼ばれる

*2:参考:RFC2076

*3:iso-2022-jpは7ビットJISとも呼ばれ、日本語を7ビットで表現する文字コードです。