👏

RFC に準拠したメールアドレスについて

2021/05/17に公開

はじめに

メールアドレスのバリデーションをする際、 RFC に準拠していないメールアドレスについても考慮しないといけなかったりする。
その時思ったのが、そもそも RFC に準拠した RFC とは何ぞやとなった。なので、この記事ではメールアドレスの形式について RFC ではどう定められているかを見ていく。

どの RFC で定められているのか

メールアドレスの形式については RFC 5321 (Simple Mail Transfer Protocol, SMTP) と RFC 5322 (Internet Mesage Format, IMF) で定められている。今回は後者の RFC 5322 の section 3.4.1 Addr-Spec Specification を見ていく。目標は有効なメールアドレスの形式を理解すること。つまり addr-spec の本質部分を理解することである。

ABNF 記法で書かれた定義を読み取っていく

目標を達成することは、 ABNF を読み取っていくことに他ならない。ドキュメントに倣い ABNF 記法で書き連ねていき、その説明を載せていく。
ABNF 記法(RFC 5234)はすでに知っているものとする。

また、今回は obs-* の定義には触れない。というのも廃止された構文として section 4 で(互換性のため?)定義されているためである。

前提となるもの(ABNF編)

ABNF 記法の RFC の Core Rules で今回使うものを載せておく。

         SP             =  %x20
         HTAB           =  %x09
                                ; horizontal tab
         WSP            =  SP / HTAB
                                ; white space

         CR             =  %x0D
                                ; carriage return
         LF             =  %x0A
                                ; linefeed
         CRLF           =  CR LF
                                ; Internet standard newline

         DQUOTE         =  %x22
                                ; " (Double Quote)

         DIGIT          =  %x30-39
                                ; 0-9
         ALPHA          =  %x41-5A / %x61-7A   ; A-Z / a-z
         VCHAR          =  %x21-7E
                                ; visible (printing) character

前提となるもの(IMF編)

Folding White Space and Comments

section 3.2.2 にある空白とコメントについての定義。

   FWS             =   ([*WSP CRLF] 1*WSP) /  obs-FWS
                                          ; Folding white space
   ctext           =   %d33-39 /          ; Printable US-ASCII
                       %d42-91 /          ;  characters not including
                       %d93-126 /         ;  "(", ")", or "\"
                       obs-ctext
   ccontent        =   ctext / quoted-pair / comment
   comment         =   "(" *([FWS] ccontent) [FWS] ")"
   CFWS            =   (1*([FWS] comment) [FWS]) / FWS

comment というのは () ではさまれたものを指し、 CFWS は空白改行と comment で作られるものを指している。ここで定義しているのは、今回知りたいこと本質からずれるため、簡単に流しておく。

Atom

section 3.2.3 にある Atom についての定義。ココが本質的な部分となる。

   atext           =   ALPHA / DIGIT /    ; Printable US-ASCII
                       "!" / "#" /        ;  characters not including
                       "$" / "%" /        ;  specials.  Used for atoms.
                       "&" / "'" /
                       "*" / "+" /
                       "-" / "/" /
                       "=" / "?" /
                       "^" / "_" /
                       "`" / "{" /
                       "|" / "}" /
                       "~"
   atom            =   [CFWS] 1*atext [CFWS]
   dot-atom-text   =   1*atext *("." 1*atext)
   dot-atom        =   [CFWS] dot-atom-text [CFWS]
   specials        =   "(" / ")" /        ; Special characters that do
                       "<" / ">" /        ;  not appear in atext
                       "[" / "]" /
                       ":" / ";" /
                       "@" / "\" /
                       "," / "." /
                       DQUOTE

atext というのは、アルファベット(A-Z と a-z)と数字(0-9)といくつかの記号(!#$%&'*+-/=?^_`{|}~)のどれか一文字を表す。

  • 33-4
  • nandeya
  • hanshin!
  • kankei_naiyaro???
  • ###++++--
  • {$//=^~}

dot-atom-text と(本質的な部分で一致している dot-atom) については、 atext が一文字以上連なったものの後に、0個以上の、 .atext が一文字以上連なったものを表している。

  • osushi
  • hito.#no.{okane}.|de|.yakiniku!.tabetai++++

Quoted characters & Quoted Strings

section 3.2.1 の Quoted characters である。

   quoted-pair     =   ("\" (VCHAR / WSP)) / obs-qp

バックスラッシュ \ と半角スペースまたは可視文字の組み合わせである。つまりエスケープを表している。

一方、 section 3.2.4 の Quoted Strings を見ていく。

   qtext           =   %d33 /             ; Printable US-ASCII
                       %d35-91 /          ;  characters not including
                       %d93-126 /         ;  "\" or the quote character
                       obs-qtext
   qcontent        =   qtext / quoted-pair
   quoted-string   =   [CFWS]
                       DQUOTE *([FWS] qcontent) [FWS] DQUOTE
                       [CFWS]

qtext がコメントにあるように VCHAR から \" を省いた文字である。 qcontentqtextquoted-pair のどちらかを指し、 quoted-string はダブルクォーテーションで囲まれた 0 文字以上の qcontent である。

  • "star-hoshii"
  • "5000-"cho"-en\hoshi"

addr-spec について

今回解読する addr-sepc は下記のように定義されている。

   addr-spec       =   local-part "@" domain

これは local-partdomaim@ で結び付けられている。

local-port について

   local-part      =   dot-atom / quoted-string / obs-local-part

local-part で使えるものは、一つ目として dot-atom つまり、 A-Z, a-z, 0-9, !#$%&'*+-/=?^_{|}~ の文字であり、 .を使う際は最初と最後にが来ずかつ連続して使われない文字列である。 二つ目のquoted-stringについては、ダブルクォーテーションでくくられている場合、 エスケープ処理が必要な文字があるがVCHAR` 全部使うことができる。

  • among-us.zutto.yaritai!
  • 18782+18782=37564
  • "(x+y)^2=x^2+2xy+y^2"
  • "...................."

domain について

   domain          =   dot-atom / domain-literal / obs-domain
   domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
   dtext           =   %d33-90 /          ; Printable US-ASCII
                       %d94-126 /         ;  characters not including
                       obs-dtext          ;  "[", "]", or "\"

domain で使えるのは、 local-part と同じように dot-atom と、 []\ を使っていない文字列で [] で囲まれたものである。

  • [????????.........########]

結論

以上のことから、使われる文字は制限されているものの、 "[] で囲むことによってほとんどの文字が使える(初めて知った)。

補足

文字数制限

   addr-spec       =   local-part "@" domain

これを満たしている addr-spec なら何でもメールアドレスとして使えるのか?と言われると No である。それは文字数制限があるからである。

文字数については、今まで見てきた RFC 5322 (IMF) では規定されていなく RFC 5321 (SMTP) の方で規定されている。

section 4.5.3.1 にはこう記載されている。

4.5.3.1.1. Local-part

The maximum total length of a user name or other local-part is 64
octets.

4.5.3.1.2. Domain

The maximum total length of a domain name or number is 255 octets.

なので local-part 部分の最大文字数は 64 文字であり、 domain 部分の最大文字数は 255 文字である。

ただ RFC 3696 によると、

A DNS label may be no more than 63 octets long.

とあるので domain 部分は 63 文字以下にしておいた方が無難である。

Discussion