こんにちは、そろそろ家の更新時期が迫ってきて引越し先の物件に悩んでいるしっぽくんです。最近業務でメールアドレスについて触れる機会があったので今回はそのお話をしようかと思います。
私自身あまり馴染みのなかった「RFC違反メールアドレス」について深堀っていく記事になりますので、ご興味あればご一読いただけると幸いです。
この記事で触れること
- RFC違反メールアドレスとはどういうことなのか
- HTML標準やバリデーションライブラリにおけるメールアドレスについて
違反しているメールアドレス??
さてこの中に仲間外れがあります。どれでしょう?
正解は2です。これ以外は違反しているメールアドレスです!具体的にどんな違反メールアドレスなのでしょうか?
前置きを踏まえて、私達の日頃の業務の中でお客様からの問い合わせで回答の難しいものが開発チームに回ってくることがあります。弊社のシステムの中でメール送信を扱うものがあり、今回の問い合わせはそれでした。
一口にメールが届かないと言っても原因は様々ありますが、今回の問い合わせはどうやら「RFC違反メールアドレス」というものでした。(ここでは原因の特定には触れません)
「 はて、RFC違反ってなんだ??」
あいにくとメール送信に関する知識は遠い昔の学生時代に触れた程度で、「RFC」という存在も恥ずかしながら知りません。
知らないなら知る機会!
一個ずつ調べてみることにしました。
RFCとは?
全くわからない概念なのでChatGPTさんに聞いてみることに。
「RFCって何?要約して教えて下さい」
RFCとは、"Request for Comments"の略で、インターネット技術に関する文書の標準化プロセスを定義する文書のことです。これは、インターネットのプロトコルや手順に関する提案や仕様を共有し、議論するためのものです。RFCは、インターネット技術の進化と標準化を促進するために広く使用されています。
なるほど、プロトコルを定義しているもの。今回だとメールアドレスのプロトコルが記載されているRFCがあると推察。
「メールアドレスに関するRFCはありますか?」
はい、メールアドレスに関するRFCはいくつか存在します。その中でも代表的なものはRFC5321(Simple Mail Transfer Protocol)とRFC 5322(Internet Message Format)です。これらのRFCは、電子メールの送信や受信に関するプロトコルやフォーマットについて定義しています。
お目当てのものが見つかりました。さてここからはどんな内容が違反になっているのかを調べてみましょう。
余談ですが、日頃触れているフレームワークなどでも採用されています。言われてみると確かに見てましたね…。
RFC5322を追え🏃♂
RFC5321はメール送信に関するプロトコルについて書かれているので、フォーマットに関して書かれているRFC5322の特にsection-3#Syntaxを見て正しいメールアドレスのフォーマットを調べてみます。
以降の要約などは自分の解釈に基づいたもののため、一部間違っている可能性があります。
もし間違っている場合は大変勉強になるためご指摘いただけると幸いです。
さて何もわからないので、順番に上から見ていきます。
前提(RFC5234)
The following primitive tokens that are used but otherwise unspecified are taken from the "Core Rules" of [RFC5234], Appendix B.1: CR, LF, CRLF, HTAB, SP, WSP, DQUOTE, DIGIT, ALPHA, and VCHAR.
どうやらRFC5234なるものがでてきました。どうやら独自定義があるようです。しかし見てみると意外とこれまで見聞きしたものがいくつかでてきていますね。
RFC5234#appendix-B.1から引用。
また述べられているものだけピックアップしています。
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
CR = %x0D
; carriage return
CRLF = CR LF
; Internet standard newline
DIGIT = %x30-39
; 0-9
DQUOTE = %x22
; " (Double Quote)
HTAB = %x09
; horizontal tab
LF = %x0A
; linefeed
SP = %x20
VCHAR = %x21-7E
; visible (printing) characters
WSP = SP / HTAB
; white space
In some of the definitions, there will be non-terminals whose names start with "obs-". These "obs-" elements refer to tokens defined in the obsolete syntax in section 4.
廃止された定義もある。
Atom
section 3.2.3では基本となる構成について書かれていました。
Several productions in structured header field bodies are simply strings of certain basic characters. Such productions are called atoms.
atoms
と呼ばれる基本構成があるとのこと。先程述べたRFC5234のプリミティブトークンと合わせて使うのでしょうか?
Some of the structured header field bodies also allow the period character (".", ASCII value 46) within runs of atext. An additional "dot-atom" token is defined for those purposes.
atext
と呼ばれるものの中に .
を許可するものもあり、それを dot-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
上記の表を見ると、RFC5234で出てきたプリミティブトークンと特定の文字を組み合わせて構成されているみたいですね。
atext
はアルファベット(A-Z, a-z)と数値(0-9)、!#$%&'*+-/=?^_`{|}~
を含むものと定義されています。
dot-atom-text
(≒ dot-atom
)は 1文字以上のatext
を含み、0個以上の.
とatext
で連なったものと定義されています。
Quoted characters & Quoted Strings
section 3.2.1とsection 3.2.4では少し似たような内容に触れていたので合わせて紹介します。
quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
3.2.1のquoted-pair
では \
と VCHAR
もしくはスペースで構成されており、エスケープを意味しています。
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
から \
と "
を除いたもので構成され、qcontent
は qtext
もしくは quoted-pair
によって構成されています。
さらに quoted-string
は "
で囲まれた0個以上の qcontent
になっています。
Addr-Spec Specification
section 3.4のaddr-spec
、ついにメールアドレスのフォーマット定義にたどり着きました、長かったです。
addr-spec = local-part "@" domain
addr-spec
は @
で仕切られたlocal-part
とdomain
に分かれています。
local-part = dot-atom / quoted-string / obs-local-part
domain = dot-atom / domain-literal / obs-domain
更に local-part
は dot-atom
または quoted-string
によって構成されています。
今回の主題である「違反しているメールアドレス」はこのlocal-part
の定義を紐解けば理解できそうです、燃えてきました。
まとめ
これまでの調べでメールアドレスは local-part
@ domain
に分かれていることがわかりました。
更に local-part
は dot-atom
もしくは quoted-string
によって成り立っています。
dot-atom
は 1文字以上の atext(アルファベット(A-Z, a-z)と数値(0-9)、!#$%&'*+-/=?^_`{|}~)
を含み、0個以上の.とatextで連なったものと定義されています。
つまり、 .
開始ではなく、.
が2つ以上連続していない、 atext
に定義されている文字で構成されたものであれば正しいメールアドレスと言えそうです。
ただし quoted-string
はこれに該当せず、 "
で囲まれた VCHAR(ただし\と"は除く)
とエスケープによって構成されているので、基本的には "
で囲めばだいたい処理されそうですね。
最後に簡易的なテーブルでまとめてみました。
要素 | 説明 | 例 |
---|---|---|
local-part |
@ の前の部分 dot-atom もしくは quoted-string で構成 |
test.test |
domain |
@ の後の部分 dot-atom もしくは domain-literal で構成 |
example.com |
dot-atom |
1文字以上の atext を含み、0個以上の. とatext で連なったもの |
test.test |
quoted-string |
" で囲まれた文字列 |
"test.test" |
atext |
アルファベット(A-Z, a-z)、数値(0-9)、!#$%&'*+-/=?^_`{|}~ を含む文字 |
test |
余談:メールサービスの対応
メールアドレスといえば各キャリアが提供する「キャリアメール」もありますね。
各キャリアでは「RFC違反メールアドレス」をどう扱っているのでしょうか?
RFC違反アドレスに関しては現在ご利用が推奨されていないため、今後メールサービスでの障害が発生する場合があります。
auメール(@au.com/@ezweb.ne.jp)を送信できないことがあります。
メールアプリによってはサポートされていません。
どこも非推奨と書かれています。
しかしながら利用ユーザーは最初に作ったメールアドレスを変更する手間もあるため、非推奨と言えど利用されている現状です。
更に余談:開発視点から見たメールアドレス
メールアドレスと言えばブラウザ上で入力する機会も多いですね。私達が開発しているシステムもそうです。
ではHTMLの仕様ではどう定義されているのでしょうか?
email = 1*( atext / "." ) "@" label *( "." label )
label = let-dig [ [ ldh-str ] let-dig ] ; limited to a length of 63 characters by RFC 1034 section 3.5
atext = < as defined in RFC 5322 section 3.2.3 >
let-dig = < as defined in RFC 1034 section 3.5 >
ldh-str = < as defined in RFC 1034 section 3.5 >
見慣れた文字が存在しますね・・・。
丁寧なことに正規表現も記載されています。
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
しかし先程まで見ていた定義と少し異なり、 local-part
が 1個以上の atext
もしくは .
となっています。
なぜ異なっているのかの理由までは調べきれなかったのですが、今回の問い合わせ同様既に作られているメールアドレスを入力できない状態を避けるためだと思われます。
もういっちょ余談: バリデーションライブラリ
ついでバリデーションライブラリについても調べてみました。
- Yup
- Zod
- Go言語のnet/mail(バリデーションライブラリではないですが)
最後に
メールアドレス1つとっても規格は様々で一概にこれでOKということはなさそうですが、送れないケースの1つとして認識しておいたほうがよさそうです。
また非推奨になっているもののまだ利用されているユーザーはいるため、対応の可否が求められそうです。
PR
株式会社HRBrainでは、一緒に働く仲間を募集しています!