メールのContent-Header, Content-Body の仕様(RFCのピックアップまとめ)

世界中で標準となっているeメール仕様(SMTPプロトコル仕様)はRFC822などのRFCドキュメントです。
原本を読めばすべて書かれているのですが、全部読むのは大変なのでピックアップしてまとめてみました。


– HTMLメール、添付ファイルなどが入ると複雑になりますが、全ての基本はRFC822に記載されているテキストメール仕様です。
– OSによらず、メールの改行はCRLF(0x0D,0x0A)を使います。
– NULL文字(0x00)の使用は禁止されています。
– HTMLメールなどを含む形態としてMIMEメールが標準化(ex. RFC2046)されました。
– ASCIIコードのFF(0x0C/Ctrl+L)は改ページを表します。
– ASCIIコードのHT(0x09/Tab)はタブ文字を表します。
– メール送信に使われるSMTPプロトコルはHTTPプロトコルと大体同じ書式を持っていて、Content-HeaderとContent-Bodyに分かれています。
– メールにはASCII文字(0-127の範囲)しか含んではいけないという決まりがあるため、日本語を扱うには文字コードをiso-2022-jpにエンコードするか、Base64などでテキストエンコードする必要があります。(iso-2022-jpはRFC2047で規定された文字コードです)。
– 半角カナはiso-2022-jpの規格外のため、利用できません。半角カナをどうしても使う必要がない場合は、メーラーで全角カナに変換したほうがいいです。
メールサーバ・メーラーソフトによっては、半角カナは全角カナに自動変換されます。(2017-3-27補足: base64エンコードなどでエンコードすれば、UTF-8/SJISのまま送れるので半角カナを使うこともできます)
– Content-Body は CRLFを除き1行は998バイト以下が必須、78バイト以下が推奨されています。ただしメーラーでこれをチェックして自動改行を行う場合は Quoted-Printable 等を使うべきです。

<Content-Header>

  • ヘッダの各行の書式は、Field-name:Value のようにセミコロン区切りでキー・値の組み合わせになっています。
  • ヘッダ終端は空行です。
  • Field-nameは文字の大小を区別しません。
  • 1つのヘッダについて複数行記述可能で、複数行にわたる場合は行頭にタブか半角空白を入れます。
  • 1行は末尾のCRLFを除いて76バイトまでという制約があります。
  • ()で囲むとその部分は制御上はコメントとして無視されます。
  • エンコードは、

=?文字コード?符号化方式?データ?=

のようにします。符号化方式はアルファベット1文字であらわし、B(Base64),Q(Quoted-printable)のいずれかを指定します。

  • ヘッダにおける符号化の規約としてダブルクオート「”」の間の文字列はエンコード/デコードしてはなりません。
    (Outlook Expressは余裕で規約違反をして、逐一””を使い、かつその中で符号化していますが。。ヘッダの符号化は MIME-VERSION:1.0 でなくても利用可能です。)
  • 宛先は、
    To: {Mail-address | 名前 <Mail-address>}

    というヘッダに書きます。複数指定可で、複数になる場合はカンマ「,」で区切ります。もし改行したい場合は、カンマの後が推奨されています。

  • 名前にカンマ’,’など特殊文字を使いたい場合はダブルクオート'”‘で囲まなければなりません。
To: グループ名:Mail-address,Mail-address,...;

とするとメーラーによっては送信時にグループ単位送信を行います。
送信時に’:’から’;’の間の文字列を削除するため、同グループ内の他人同士は匿名になります。
その際の受信側ヘッダは次のようになります。

To:グループ名:;
  • Cc:
    コピー送信先。書式はToと同じです。
  • Bcc:
    隠れコピー送信先。CCと同様、コピーを指定したメールアドレスに送りますが、(Bcc自身も含む)全送信者について送信前にBcc:項目を削除します。書式はToと同じです。
  • From:
    送信者のメールアドレス、名前です。書式はToと同じです。
  • Sender: mail-address
    Fromと似ていますが1つしか指定できません。Fromで複数指定した場合の実際の送信者を指定する場合に利用します。>
  • Reply-To: mail-address
    Fromとは違うあて先に返信して欲しい場合に指定します。ただし受信側メーラーに動作を任せるのでこれだけに対してのみ必ず返信になるという保証はありません。
  • Date: GMT-Date-and-Time
    送信時刻です。

    書式 = 曜日, 日 月 年 時:分:秒 ゾーン

    曜日は省略可。曜日と月は英語3文字です。
    ゾーンは標準時刻からの時差と地域をあらわします。
    ゾーン = 時差

    例)Date: Sat, 1 Aug 1998 14:23:33 +0900 (JST)
  • Subject: title
    メールの題名です。
  • X-*
    X-ではじまるヘッダはユーザー定義フィールドで、任意の名前のヘッダを追加することができます。
    標準的なものを挙げると、

X-Mailer: Mailer-Software-Name
メーラーの識別子、OS情報など

X-Face:????
小さな顔写真を格納、表示できる

といったものがあります。

  • Message-ID: <メール固有のID>
    メール固有のID(通例、送信元メールアドレスの前に時間情報と’.’を付加したもので、メールアドレスが省略されることもあります)を
    <>で囲みます(RFC2111で規定)。

    例) Message-ID: <237820.foo@sample.com>

    他のメッセージから

    "mid:" message-id/content-id

    という書式で参照できます(/content-idは省略可)。

IDのフォーマットはRFC822では次のように定められています。

msg-id      =  "&lt;" addr-spec "&gt;"
addr-spec   =  local-part "@" domain        ; global address
local-part  =  word <em>("." word)             ; uninterpreted
                                            ; case-preserved
 word        =  atom / quoted-string
atom        =  1</em>&lt;any CHAR except specials, SPACE and CTLs>
specials    =  "(" / ")" / "&lt;" / ">" / "@"  ; Must be in quoted-
                /  "," / ";" / ":" / "\" / &lt;">  ;  string, to use
/  "." / "[" / "]"              ;  within a word.
CTL         =  &lt;any ASCII control           ; (  00- 037,  0.- 31.)
                    character and DEL>          ; (    0177,     127.)
    quoted-string = &lt;"> <em>(qtext/quoted-pair) &lt;">; Regular qtext or
                                                ;   quoted chars.
qtext       =  &lt;any CHAR excepting &lt;">,     ; => may be folded
             "\" &amp; CR, and including
                  linear-white-space>
  linear-white-space =  1</em>([CRLF] LWSP-char)  ; semantics = SPACE
                                              ; CRLF => folding
      LWSP-char   =  SPACE / HTAB                 ; semantics = SPACE
      HTAB        =  &lt;ASCII HT, horizontal-tab>   ; (011,9.)

<pre><code>  quoted-pair =  "\" CHAR                     ; may quote any char
  CHAR        =  &amp;lt;any ASCII character&gt;        ; (00-0177, 0.-127.)

  domain      =  sub-domain *("." sub-domain)
  sub-domain  =  domain-ref / domain-literal
  domain-ref  =  atom                         ; symbolic reference
  domain-literal =  "[" *(dtext / quoted-pair) "]"
  dtext       =  &amp;lt;any CHAR excluding "[",     ; =&gt; may be folded
               "]", "\" &amp;amp; CR, &amp;amp; including
            linear-white-space&gt;
</code></pre>

– In-Reply-To: <メール固有のID>
メールを返信する際、元のメールのMessage-IDを指定すると元のメールと関連付けることが出来ます。

  • References:<メール固有のID> <メール固有のID> <メール固有のID> …
    関連ある電子メールを複数記述できるヘッダです。
  • Received: from mailgate-server-address (????-address [IPv6]) by received-address; GMT-Date-and-Time
    メール送信における中継配送システム情報です。
    Receivedは1つ以上存在し、通例として新しいものは古いものの前に付加される。このヘッダは自動で受信側サーバが付与するものです。直近のものほど信頼性があります。
    各項目の意味は以下のとおりです。
    from 送信サーバホスト名 (IP逆引きホスト名 [xxx.xxx.xxx.xxx])
    by 受信サーバホスト名
    ; 中継時刻

  • MIME-Version: version-number
    省略した場合テキストメールになります。
    指定した場合MIMEメールとして扱われます。
    このヘッダはRFC2045で規定されています。

例)MIME-Version: 1.0

  • Content-*
    MIMEで使うフィールドとして予約されており、Content-から始まるヘッダについては各パートは完全に独立しています。
  • Content-Type: MIME-TYPE; parameter
    MIME-version:1.0で対応。これによりメールのデータ形式が定義されます。
    parameterはセミコロンで区切りparam=valueの形で記述します。
    MIME-TYPEはスラッシュで主型、副型に分けられ、不明な副型の場合主型で標準のものが採用されます。
    パラメータの種別は主型によります。

  • 例) Content-Type: text/plain; charset=iso-2022-jp

    MIME-TYPE一覧: http://www.geocities.co.jp/Hollywood/9752/mime.html
    その他: RFC2046
    MIME-TYPE = (一例)

    text/ : テキスト系
    parameter = 
    charset: 文字コード.
    iso-2022-jp=日本語,US-ASCII=英語(デフォルト),ISO-8859-1=欧系言語
    format:????
    flowed=????
    name: ファイル名。Content-Disposition: attachmentがあるのでいらないような。
    x-unix-mode: UNIXにおけるパーミッションを8進数で(0644
      plain: 通常のテキストベースメール(デフォルト)
        html: HTMLメール
        img/ : 画像系
    
    <pre><code>Multipart/ : マルチパート系。これにより複数のパートを再帰的に格納できるようになる(フォルダに譬えられる)
    Content-Type:Multipart/*; のContent-Bodyの内容は完全に無視される。
    parameter = 
    boundary:パートの区切り子の名前。"〜"のようにダブルクォートで囲む。
    各パートは独立したContentとなり、通常のテキストメールと同じ
    header/body 構成になる。区切り子には先頭に'--'を付加したものが、
    終端子にはさらに後ろにも'--'を付加したものを使う。区切り子の前は
    ヘッダと同様空行にする。(ただしヘッダを省略した場合は末尾の空行は不要/終端子の後のデータは無視される)
    [boundaryに使える文字列定義](RFC2046-P21)
    </code></pre>
    
    
        boundary := 0*69<bchars> bcharsnospace
        bchars := bcharsnospace / " "
        bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
                              "+" / "_" / "," / "-" / "." /
                            "/" / ":" / "=" / "?"
    

    例)

    Content-Type: Multipart/Mixed;boundary=foo
    Content-Transfer-Encoding: 7bit
    
    --foo
    Content-Type: text/plain; charset=iso-2022-jp
    Content-Transfer-Encoding: 7bit
    
    Hello,world!
    
    --foo
    Content-Type: text/plain; charset=iso-2022-jp
    Content-Transfer-Encoding: 7bit
    
    あいうえお
    
    --foo--
    

    Mixed: 多種のパートを混在させるという宣言(省略時デフォルト)。添付ファイル等に使います。
    alternative: 同一の内容を複数のMIME-TYPEで記述するという宣言で、受信メーラーによってタイプを選択させるためのものです。(text/plainとtext/html 等)
    related: 各パートがリンクしている事を宣言で、HTMLからのContent-ID(CID:〜)による呼び出しができるようにします。
    parallel: Mixedとほぼ同じだが、複数パートを順序を問わず同時実行されます。事実上、多くのメーラーは連続的に実行します。
    digest: それぞれのパートのデフォルトMIME-TYPEがmessage/rfc822とされます。
    Message/
    Rfc822 : メールの転送・カプセル化(RFC2046-5.2)
    トップレベルでの利用の場合、Recent-From,Recent-To,Recent-Date等を送信時にFrom,To,
    Dateの代わりに使うが、その際、受信側の返信先はFromになります。
    もうひとつの方法として Multipart/Mixedのパートの一部に含めてカプセル化することも可能です。
    Partial: この説明は今回はパスします(RFC2046-P29参照)
    content-transfer-encodingは7bitでなければなりません。
    external-body: 外部(ファイル)参照(RFC2046-5.2.3)
    parameter =(RFC2046-5.2.3.1)
    [共通]
    access-type: アクセス形式(文字の大小を問いません)
    local-file=nameはメール受信側のローカルファイルパスになります
    その他 mail-server,ftp,anon-ftp,tftp, x-*
    expiration: 有効期限. GMT-Date-Timeを記述します(省略可
    その他,parmission,size
    [ftp/tftp]
    name: ファイルパス
    site: アクセス先ドメイン
    以下略
    [local-file]
    name: ファイルパス
    以下略
    Content-Bodyの直前にさらに参照先ファイルのためのContent-Headerを書きます。
    第二のContent-HeaderにはContent-IDを含むべきです。
    それ以下のContent-Bodyの意味はaccess-typeにより異なります。local-fileの場合は使いません。
    content-transfer-encodingは7bitでなければなりません。
    – Content-Transfer-Encoding: type
    MIME-version:1.0で対応していて、これによりContent-Bodyの符号方式が定義されます。
    type =
    7bit : 無変換。Content-Bodyを7bit(文字コード 0-127)の行の集合とします(デフォルト)
    8bit : 無変換。7bitの定義のうち1バイトでも8bitが含まれるもの。
    binary : 無変換。その他。
    base64 : 64進数エンコード。[A-Za-z0-9+/]の64文字で表されます。
    quoted-printable : 特殊文字を”=16進数”で表現します。=は”=3D”のようにエンコードする。長い行は行末に=をつけ改行されます。
    Multipart,Messageは無変換でなくてはなりません。
    – Content-Description: message
    パートに対する説明。like the header “subject”
    – Content-Disposition: attachment; filename=”filename”
    そのパートをファイルとして保存する場合のファイル名を”〜”の中に指定できます。
    attachment は添付ファイルとして扱うことを宣言しますあ。
    – Content-ID: <パート固有のID>
    同一RelatedパートのHTMLからURIとして”cid:part-ID”として参照できます。定義と利用の順番は問いません。
    例)

    Content-ID: <foo1234>
    

    という画像パートがある場合

    <img src="cid:foo1234">
    

    で表示できる。(RFC2111) 書式は Message-ID とまったく同じです。