RFC 5322 & 5321に沿ったメールアドレス（local-part）に使える文字まとめ

メールアドレスの仕様について気になったので調べたことをまとめました。
そしてテストデータを少しばかり考えてみました。
何か違っている所があればご指摘いただけると助かります。
いやぁ…RFC準拠のメールアドレスのテストって難しいですね。
（というかRFC読むのが難しかった…です）

## 現在(2019/01/20)のメールアドレスに関わるRFC
- [RFC 6854](https://www.rfc-editor.org/info/rfc6854) (Updates [RFC 5322](https://www.rfc-editor.org/info/rfc5322))
- [RFC 7504](https://www.rfc-editor.org/info/rfc7504) (Updates [RFC 5321](https://www.rfc-editor.org/info/rfc5321) & [RFC 1846](https://www.rfc-editor.org/info/rfc1846))

※ 6854と7504は一部追加・変更のようなので、多くの部分は5322と5321となっているようです。

## (余談)そもそもRFCとは？
IETF（Internet Engineering Task Force）が発行している、技術仕様などについての文書群です。
IETFはインターネット技術の標準化などを行っています。 

※ RFC → Requests For Commentsの略称
※ IETF公式：[IETF | Internet Engineering Task Force](https://www.ietf.org/)
※ 参考：[RFC【Request For Comments】 - IT用語辞典](http://e-words.jp/w/RFC.html)

## (余談)RFCは廃止・更新されるもの
RFCは技術仕様の標準的なものが書かれています。
当たり前のことですが技術は進化するものなので、廃止・更新されていきます。

例えば[RFC 2822](https://www.rfc-editor.org/info/rfc2822)について。

![スクリーンショット 2019-01-20 18.22.42.png](https://qiita-image-store.s3.amazonaws.com/0/259668/eaa9701e-6b25-fdf5-3c72-ed8b9c7bb78a.png)
このRFC 2822は他のRFCと以下のような関係になっています。

- Obsoletes: RFC 822
    - RFC 822を廃止して、RFC 2822になりました
- Obsoleted by: RFC 5322
    - RFC 2822は廃止され、RFC 5322になりました
- Updated by: RFC 5335, RFC5336
    - RFC 5335, RFC 5336はRFC 2822を一部更新したものです

なので、現在どのRFCが最新なのか？については、↑のサイトからたどることができます。
便利ですね。

※ [【インターネットはこうして創られている～IETFの仕組み】 第3回：RFCの読み方 - INTERNET Watch Watch](https://internet.watch.impress.co.jp/docs/column/ietf2009/324722.html)
※ [第2回　Internet StandardsとRFC (6/6)](http://www.atmarkit.co.jp/ait/articles/0006/13/news001_6.html)

## メールアドレスに関わるRFC
さて、メールアドレスに関わるRFCですが、冒頭に書いたように以下のものが現在の最新のようです。

- [RFC 6854](https://www.rfc-editor.org/info/rfc6854) (Updates [RFC 5322](https://www.rfc-editor.org/info/rfc5322))
- [RFC 7504](https://www.rfc-editor.org/info/rfc7504) (Updates [RFC 5321](https://www.rfc-editor.org/info/rfc5321) & [RFC 1846](https://www.rfc-editor.org/info/rfc1846))

※ この記事ではメール本文の構造などは取り扱わず、メールアドレス(xxx@xxx)がどういう仕様なのか？に注目したものなので、RFC5321とRFC5322を参考しています。

## RFCに基づくメールアドレスの仕様

そもそもWikipediaにわかりやすく書かれてました！
パッと見たい方はぜひご参考ください。
[メールアドレス - Wikipedia](https://ja.wikipedia.org/wiki/メールアドレス)

↓はRFC本文や他の方のブログなどを読みながら書いたものになります。

### ① メールアドレスの構造
メールアドレスは以下の構造で定義されています。 
**local-part@domain**

### ② 文字数
それぞれ最大文字数が定義されています。

- local-part: 最大64文字
- domain: 最大253文字（RFCでは、255文字と書かれているが、別途識別に文字が2文字分必要なので）
- local-part@domain 全体: 最大254文字 (RFCでは、256文字と書かれているが別途識別に文字が2文字必要なので)

ということで、local-partに最大の64文字使った場合は、domainは`254 - 64 - 1`で189文字となります(- 1は`@`分)。
もちろん、domainに253文字使った場合は、`254 - 253 - 1` でlocal-partが0文字になってしまうので、現実的にはdomainが253文字使われるというケースはなさそうですかね(- 1は`@`分)。
また、local-partの定義的にはnullが許容されてなさそうです。
最低1文字は必要そうです。

### ③ local-partに使える文字の種類
全角文字は使えません。
すべて半角になります。

1. 無条件で使える: 81文字
    1. アルファベット（大文字 & 小文字)52文字 → A~Z, a~z
    1. 数字10文字 → 0~9
    1. 記号19文字 → `!` `#` `$` `%` `&` `'` `*` `+` `-` `/` `=` `?` `^` `_` ``` ` ``` `{` `|` `}` `~` 
1. 先頭と末尾以外、かつ連続しなければ使える（末尾=`@`の直前）: 1文字
    1. ドット → `.`
1. ダブルクオートでくくると使える: 93文字
    1. 無条件で使えるもの81文字
    1. ドット(連続しよう可) → `.`
    1. 記号10文字 → `(` `)` `,` `:` `;` `<` `>` `@` `[` `]`
1. ダブルクオートでくくる & バックスラッシュをつけると使える: 97文字
    1. ダブルクオートでくくると使えるもの93文字
    1. バックスラッシュと連続すると使える4文字(最後の2つは半角スペースとタブです) → `"` `\` ` ` `タブ` 

- 原文: 
    - [RFC 5322](https://www.rfc-editor.org/info/rfc5322)
    - [RFC 5321](https://www.rfc-editor.org/info/rfc5321)
- 参考: 
    - [RFC5322(Internet Message Format)](http://srgia.com/docs/rfc5322j.html)
    - [RFC5321(Simple Mail Transfer Protocol)](http://srgia.com/docs/rfc5321j.html)

## メールアドレスのテストデータ例

何かのご参考になればと思います。

### メールアドレスとして成立するもの

| local-partのデータ | 適用されるルール(数字は③をもとに) | 補足 |
| --- | --- | --- |
abcdefghijklmnopqrstuvwxyz | 1.1 アルファベット小文字 | -
ABCDEFGHIJKLMNOPQRSTUVWXYZ | 1.1 アルファベット大文字 | -
0123456789 | 1.2 数字 | -
!#$%&'*+-/=?^_{&#124;}~`| 1.3 記号 | -
a.b | 2.1 ドット | -
"abcdefghijklmnopqrstuvwxyz" | 3.1 ダブルクオート + アルファベット小文字 | -
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 3.1 ダブルクオート + アルファベット大文字 | -
"0123456789" | 3.1 ダブルクオート + 数字 | -
"!#$%&'*+-/=?^_{&#124;}~`"| 3.1 ダブルクオート + 記号 | -
"." |  3.2 ダブルクオート + ドット | -
".." |  3.2 ダブルクオート + ドット(連続) | ダブルクオートでくくると連続使用可能
" ()*,:;<>@[]" | 3.3 ダブルクオート + 記号 | -
"\a\A\0\\!\\." | 4.1 ダブルクオート + バックスラッシュ + 3.3までに成立したもの | テストデータよく考えたほうが良いです
"\\\"\ \  " | 4.2 ダブルクオート + バックスラッシュ + 記号 | スペースとタブを含んでいます
0123456789012345678901234567890123456789012345678901234567890123 | - | 64文字


### メールアドレスとして成立しないもの

| テストデータ | 適用されるルール(数字は③をもとに) | 補足 |
| --- | --- | --- |
.aaa | 2.1 ドット | .先頭はNG
aaa. | 2.1 ドット | .が最後はNG
a..a | 2.1 ドット | ダブルクオートでくくらずに.が連続するのはNG
() | 3.3 ダブルクオート | ダブルクオートでくくらずに()を使用するのはNG
"aaa"a | 4.2 ダブルクオート + バックスラッシュ + 記号 | ダブルクオートは最初と最後に無いとだめ。(使う場合は\\を使う)
 | - | 空はNG
01234567890123456789012345678901234567890123456789012345678901234 | - | 65文字以上はNG
"あいうえお" | - | 全角文字はNG

## 注意点

このテストをもしするとなったとき、気をつけたほうがいいだろうなぁ…と思うことをまとめました。

### ① テストデータの取扱い: プログラム実行時に気をつける
記号系、特にダブルクオートやシングルクオートなのですが、テストデータ生成やDBに値を入れるときに、プログラムで自動実行すると意図したテストデータが入らない、プログラム実行時にエラーが起きる、といったことが発生します。
`$` `#`などはもちろん、`//` `/*`というような、プログラムのコメントアウトに使われたりするものも取扱いに注意が必要です。
状況に応じて、手動で操作することをおすすめします。

### ② テストデータの取扱い: エクセルなどの場合、コピー操作やシングルクオートに気をつける
エクセルやGoogleスプレッドシートでは、先頭にシングルクオートを入力すると、先頭が0の数字を表示してくれる機能があります。
なのでこれをうっかりしていると、先頭のシングルクオートがなくなってたり…なんてこともあるかもしれないです。
表計算ソフトなどで保管している場合は、コメントなど残しておいたほうが良さそうですね。
※ 参考: [Excelで先頭の「0」が消えるのを表示させる4つの方法｜Office Hack](https://office-hack.com/excel/display-leading-zeros/)

### ③ 本当にRFCに準拠するのかを考える
ここまで書いておいて、おいおいって感じですけどね（笑）
RFC 5821では、local-part部の大文字と小文字は区別する、と明記されています（しかし推奨しないとも書かれています）。
でも、多くのサービスでは大文字と小文字区別されていませんよね。
また記号についても、ダブルクオートやバックスラッシュを使えばたくさんの記号やスペースが使えますが、本当に対応すべきなのか考えたほうが良いかもしれません(文字数についてもそうですね)。

## (余談) Gmailのエイリアスについて

[別のアドレスやエイリアスからメールを送信する - Gmail ヘルプ](https://support.google.com/mail/answer/22370?hl=ja)
Gmailのエイリアス機能ありますよね。
local-partの直後に+を書くことで、複数のメールアドレスのように管理できる機能で、テストに関わる方はよく使っている機能の1つかと思います。
このエイリアスを使って、メールアドレスが全体が300文字以上になったアドレスに送信したところ送信 & 受信することができました。
ちなみに送信したアプリケーションはMacのThunderbirdでした。
RFC的にはメールアドレスの制限があるんですが、そうじゃないパターンでも使えるようになっているってことですよね。
便利だなぁと思います。
なのでメールアドレスを作成するときは、RFCよりも少し厳しめに制限をかけておくけど、送信・受信のときはメールアドレスの文字数をチェックしない…といった対応のほうが対応できる幅は広がりそうですね。 

## (余談) RFC 5322, 5321を読むためのメモ
RFCでは以下の用語が使われていました。
確認用のメモとして残しておきます。

### local-partで使用できる文字について
```
local-part = dot-atom / quoted-string / obs-local-part
① dot-atom
dot-atom = [CFWS] dot-atom-text [CFWS]
dot-atom-text = 1*atext *("." 1*atext)
atext = ALPHA / DIGIT /"!" / "#" /
"$" / "%" / "&" / "'" / "*" / "+" /"-" / "/" / "=" / "?" /"^" / "_" /"`" / "{" / "|" / "}" / "~"

② quoted-string
quoted-string = [CFWS] DQUOTE *([FWS] qcontent)[FWS] DQUOTE [CFWS]
qcontent = qtext / quoted-pair
qtext = %d33 / %d35-91 / %d93-126 / obs-qtext
quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
obs-qtext = obs-NO-WS-CTL
obs-NO-WS-CTL = %d1-8 / %d11 / %d12 / %d14-31 / %d127
obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)

③ obs-local-part
obs-local-part = word *("." word)
word = atom / quoted-string
```

※ ALPHA, DIGIT, VCHAR, CR, LF, CRLF, HTAB, SP, WSP, DQUOTE については[RFC 5324](https://www.rfc-editor.org/info/rfc5324)を参考にする
※ [ABNF - Wikipedia](https://ja.wikipedia.org/wiki/ABNF#%E4%B8%AD%E6%A0%B8%E8%A6%8F%E5%89%87)

- ALPHA → アルファベットの大文字と小文字
- DIGIT → 0~9の数字
- VCHAR → ASCIIで印字される文字 [ASCII - Wikipedia](https://ja.wikipedia.org/wiki/ASCII#ASCII%E5%8D%B0%E5%AD%97%E5%8F%AF%E8%83%BD%E6%96%87%E5%AD%97)
- %d33 → ASCII表で10進数で33の部分。つまり`!`
- %x41 → ASCII表で16進数で41の部分。つまり`a`

## 参考サイト
この記事を書くにあたって以下のサイトを参考にさせていただきました。

- [「メールアドレスのルール」系まとめがそろって間違ってるのでご注意を - 若き何かの悩み](http://orgachem.hatenablog.com/entry/2013/11/26/015343)
- [メールを書くときに使う文法はRFC 5322です。 - ponsuke_tarou’s blog](http://ponsuke-tarou.hatenablog.com/entry/2018/02/24/163729)
- [結局 &quot;メールアドレスの規格&quot; ってどこ？ - Qiita](https://qiita.com/wingsys/items/5c00f5ff2e34a6b7ee10)
- [「あなくつ」のおもちゃばこ - Laboratory - メールアドレス (RFCに基づく仕様を理解する)](https://www.ana-kutsu.com/laboratory/email_addr_spec.html)
- IETF公式：[IETF | Internet Engineering Task Force](https://www.ietf.org/)
- [RFC【Request For Comments】 - IT用語辞典](http://e-words.jp/w/RFC.html)
- [【インターネットはこうして創られている～IETFの仕組み】 第3回：RFCの読み方 - INTERNET Watch Watch](https://internet.watch.impress.co.jp/docs/column/ietf2009/324722.html)
- [第2回　Internet StandardsとRFC (6/6)](http://www.atmarkit.co.jp/ait/articles/0006/13/news001_6.html)
- [ドメイン名のしくみ - JPNIC](https://www.nic.ad.jp/ja/dom/system.html)
- [メールアドレス - Wikipedia](https://ja.wikipedia.org/wiki/メールアドレス)