メールのアドレスヘッダの仕様

メールの解析に頭を悩ませることが多いです。
特に "From" "To" "Cc" "Bcc" などのアドレスヘッダ部分。

そこで、どのような仕様になっているか整理しました。

まず "RFC 2822 Internet Message Format" のアドレスヘッダの定義について。RFC 2822 は最初にメールの仕様を定めた "RFC 822 STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES" を改定したものです。

("ARPA INTERNET" と呼んでいるあたりに、歴史を感じさせます。)

RFC 2822 は更に "RFC 5322 Internet Message Format" で改定作業が進んでいるようです。

アドレスヘッダの本体の部分は　mailbox-list として以下のように定義されています。簡単にするため、obs- で始まる昔の定義は省略します。

(定義は ABNF "Augmented Backus–Naur form" で記載されています。[Wikipedia の解説](https://ja.wikipedia.org/wiki/ABNF) が解りやすいでしょう。)

```
mailbox-list    =       (mailbox *("," mailbox)) / obs-mbox-list
mailbox         =       name-addr / addr-spec
name-addr       =       [display-name] angle-addr
angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
```

addr-spec はメールアドレスそのもので、display-name が表示名 です。mailbox は

- メールアドレス
- 表示名 <メールアドレス>

のいずれかの形式で、それらが "," 区切りで並んだものがアドレスヘッダになっています。

それでは表示名 display-name の定義に移ります。
表示名は atom か quoted-string の2形式のいずれの1回以上の反復になります。atom と quoted-string は混在して問題ありません。

```
display-name    =       phrase
phrase          =       1*word
word            =       atom / quoted-string
```

atom は英数字の文字列です。ただしスペースと "() など幾つかの記号は含みません。

```
atom            =       [CFWS] 1*atext [CFWS]
atext           =       ALPHA / DIGIT / ; Any character except controls,
                        "!" / "#" /     ;  SP, and specials.
                        "$" / "%" /     ;  Used for atoms
                        "&" / "'" /
                        "*" / "+" /
                        "-" / "/" /
                        "=" / "?" /
                        "^" / "_" /
                        "`" / "{" /
                        "|" / "}" /
```

表示名に " や () を使用したい時に必要なのが、quoted-string です。DQUOTE は " で、要は " で囲まれた英数字の文字列です。" の内側の制約は atom より緩く、以下の文字以外は使用可能です。
- \
- " (\" の組み合わせで使用可能)
- 改行コード
- スペース

```
quoted-string   =       [CFWS]
                        DQUOTE *([FWS] qcontent) [FWS] DQUOTE
                        [CFWS]
qcontent        =       qtext / quoted-pair
qtext           =       NO-WS-CTL /     ; Non white space controls

                        %d33 /          ; The rest of the US-ASCII
                        %d35-91 /       ;  characters not including "\"
                        %d93-126        ;  or the quote character
NO-WS-CTL       =       %d1-8 /         ; US-ASCII control characters
                        %d11 /          ;  that do not include the
                        %d12 /          ;  carriage return, line feed,
                        %d14-31 /       ;  and white space characters
                        %d127
quoted-pair     =       ("\" text)
```

最後に CFWS についてです。これは "Comments and/or Folding White Spaces" の略です。ざっくりコメントとスペース／改行コードが許されていると理解しておけば十分です。() で囲まれた部分がコメントになります。quoted-string の定義とあわせて考えると、"" で囲まれた中はコメントが許されておらず、"" の外だけ OK ということになります。

```
CFWS            =       *([FWS] comment) (([FWS] comment) / FWS)
FWS             =       ([*WSP CRLF] 1*WSP)   ; Folding white space
comment         =       "(" *([FWS] ccontent) [FWS] ")"
ccontent        =       ctext / quoted-pair / comment
ctext           =       NO-WS-CTL /     ; Non white space controls

                        %d33-39 /       ; The rest of the US-ASCII
                        %d42-91 /       ;  characters not including "(",
                        %d93-126        ;  ")", or "\"
```

これらを踏まえたサンプルです。RFC 2822 に掲載されているものです。

```
From: Pete(A wonderful \) chap) <pete(his account)@silly.test(his host)>
To: Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>
Cc: <boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>
```

以下に表示名を抜き出します。
- Pete
- Mary Smith
- Who?
- Giant; "Big" Box

RFC 2822 には、日本語など ASCII 文字以外の取り扱いがありません。その拡張を行うものが "RFC 2047 MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text" です。MIME によるメールの拡張については、RFC 2045 - 2049 の5つに分かれていて、そのうちの3番目が、メールのヘッダ部分への MIME の適応です。

MIME の仕様の詳細は省略して、MIME をどこに使用できるかについて説明します。アドレスヘッダの絡みでは以下の点がもっとも重要です。

```
+ An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'.
+ An 'encoded-word' MUST NOT appear within a 'quoted-string'.
```

つまり表示名の atom の部分 (とコメントの部分) の代わりにしか使用することができません。表示名 (display-name) についてまとめると、以下のようになります。

```
display-name    =       phrase
phrase          =       1*word
word            =       atom / quoted-string / encoded-word
```

- atom は英数文字列で、使用可能な記号に制限がある。文字列はそのまま解釈される。
- quoted-string は "" で囲まれた英数文字列。ほとんどの記号も使用可能。文字列はそのまま解釈される。
- encoded-word は MIME エンコードされた文字列。文字列は MIME デコードして解釈される。
- atom や quoted-string には、() で囲まれたコメントが含まれうる。