メールアドレスの優しいバリデーションとは
はじめに
アカウント登録のためのページを作成する際、ほぼ必須といってよい入力項目として、ユーザーID、パスワード、そしてメールアドレスがあります。
ユーザーID、パスワードについては要件によって正しいバリデーションは変わるかと思いますが、メールアドレスについては、必ずアットマークがついているなどのルールが存在することは明らかですから、正しいバリデーションが存在していそうです。そのため、実装も既存のバリデーションのライブラリを利用すれば簡単に終わると私は思っていました。
しかしながら、私は悩みました…なぜならメールアドレスの場合、正しいバリデーションがユーザーにとって優しいバリデーションとは言い切れなかったからです。
正しいバリデーション
まずは自分が最初に実装しようと考えていたメールアドレスの正しいバリデーションについて見ていきましょう。
メールアドレスには、前項でも述べたように必ずアットマークがついているなどのルールが存在しています。そういったルールはRFC(Request for Comments)と呼ばれるインターネット技術の標準的な仕様、ルールを記した文書に記載されています。
メールアドレスについてのルールは、主にRFC5321、RFC5322、RFC6531に記載があります。
メールアドレスのルール RFC5321、RFC5322
大半のバリデーションのライブラリは、RFC5321、RFC5322に準拠したものなっていますので、まずは大元となるRFC5321、RFC5322に記載されているメールアドレスのルールを見てみましょう。
RFC5321の「4.1.2. Command Argument Syntax」には以下の記載があります。
Domain = sub-domain *("." sub-domain)
sub-domain = Let-dig [Ldh-str]
Let-dig = ALPHA / DIGIT
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
address-literal = "[" ( IPv4-address-literal /
IPv6-address-literal /
General-address-literal ) "]"
; See Section 4.1.3
Mailbox = Local-part "@" ( Domain / address-literal )
Local-part = Dot-string / Quoted-string
; MAY be case-sensitive
Dot-string = Atom *("." Atom)
Atom = 1*atext
Quoted-string = DQUOTE *QcontentSMTP DQUOTE
QcontentSMTP = qtextSMTP / quoted-pairSMTP
quoted-pairSMTP = %d92 %d32-126
; i.e., backslash followed by any ASCII
; graphic (including itself) or SPace
qtextSMTP = %d32-33 / %d35-91 / %d93-126
; i.e., within a quoted string, any
; ASCII graphic or space is permitted
; without blackslash-quoting except
; double-quote and the backslash itself.
address-literal
については、See Section 4.1.3
とあるように、「4.1.3. Address Literals」で定義されています。
また、atext
はRFC5322の「3.2.3. Atom」で次のように定義されています。
atext = ALPHA / DIGIT / ; Printable US-ASCII
"!" / "#" / ; characters not including
"$" / "%" / ; specials. Used for atoms.
"&" / "'" /
"*" / "+" /
"-" / "/" /
"=" / "?" /
"^" / "_" /
"`" / "{" /
"|" / "}" /
"~"
これらからRFC5321、RFC5322に準拠した場合、ローカルパートLocal-part
(@よりも前の部分)やドメインDomain
(@よりも後の部分)は半角英数字と一部の記号のみ使用でき、ドットの連続は許可されていないことなどが読み取れます。(ただし、ローカルパートについては、ダブルクォーテーションで囲めば、使用できる記号も増えますし、ドットの連続も許可されます)
メールアドレスのルール RFC6531
ここまで見てきたRFC5321、RFC5322が主なメールアドレスのルールとなっていますがRFC6531の「3.3. Extended Mailbox Address Syntax」では、RFC5321、RFC5322のルールに以下のような拡張が行われています。
sub-domain =/ U-label
; extend the definition of sub-domain in RFC 5321, Section 4.1.2
atext =/ UTF8-non-ascii
; extend the implicit definition of atext in
; RFC 5321, Section 4.1.2, which ultimately points to
; the actual definition in RFC 5322, Section 3.2.3
qtextSMTP =/ UTF8-non-ascii
; extend the definition of qtextSMTP in RFC 5321, Section 4.1.2
esmtp-value =/ UTF8-non-ascii
; extend the definition of esmtp-value in RFC 5321, Section 4.1.2
U-label
やUTF8-non-ascii
では標準Unicodeエンコーディング形式(UTF-8など)で表現された文字列が利用可能です。これらから、sub-domain
やatext
で全角英数字、ひらがな、カタカナ、漢字などが利用できるように更新されたということを読み取ることができます。
さらに、これを先述したRFC5321の「4.1.2. Command Argument Syntax」と組み合わせるとローカルパートLocal-part
やドメインDomain
に全角英数字、ひらがな、カタカナ、漢字などが利用できるようにRFC6531で更新されたということがわかります。
RFCに準拠したバリデーションの問題点
ここまでで説明したようにRFCにメールアドレスに関するルールは明記されていますので、このルールに従っていないメールアドレスの入力を弾くのは正しいバリデーションと言えます。
ただ、私はここで疑問が生じました。この正しいバリデーションはユーザーにとって優しいバリデーションでしょうか?
このバリデーションにはユーザーにとって優しいとは言えない次の二つの問題がありそうです。
RFCに違反したメールアドレスが弾かれる
まず、一つ目の問題はRFCに違反したメールアドレスが弾かれることです。
RFCに違反したメールアドレスが弾かれるのは、問題ないようにも思えますが…docomoやauではtest..test@example.com
のようなドットが連続したローカル部をもつようなRFC違反のメールアドレスが作成可能だった期間が過去にありました。
このため、RFC違反のメールアドレスが作成可能な期間にメールアドレスを作成し、その後、メールアドレスの変更を行わずに、RFC違反のメールアドレスを利用し続けている人もまだ存在しています。
そのような人はバリデーションで弾かれて、アカウント登録できないということになりますが、それで問題ないとしてよいかは微妙なところです。
全角英数字などが使われていても弾かれない
二つ目の問題は全角英数字などが使われていても弾かれないことです。
先述のRFC6531に準拠していた場合は、全角英数字、ひらがな、カタカナ、漢字なども利用可能となります。このため、test@example.com
と入力するつもりがtest@eⅹample.com
のように全角英字を入力していても、RFC6531準拠のメールアドレスとしては正しいことから、バリデーションで弾かれなくなります。
しかしながら、現時点では、全角英字の入力はユーザーの入力ミスである場合がほとんどであるため、自分としては、これが弾かれないのは問題があるように思えます。
なお、これはバリデーションがRFC6531に準拠していた場合に生じる問題です。RFC5321、RFC5322に準拠していて、RFC6531に準拠していないメールアドレスのバリデーションでは、この問題は生じません。
RFC準拠以外のバリデーション
以上がRFCのメールアドレスのルールと、それに準拠したバリデーションの問題点になります。
では、どのようなバリデーションとすればよいのでしょうか。
実はRFC以外にも参考となる文書はあります。
HTML Living Standard のメールアドレスのバリデーション
Web系の開発を行ったことのある方なら<input type="email">
というようなタグをみたことがある方も多いかと思いますが、このタグにより、フォーム検証の仕組みや:valid
、:invalid
擬似クラスを使用して、現在の値が有効かどうかのバリデーションを行うことが可能となっています。
バリデーションを行うことが可能ということは、当然、それについての文書がありますので、今度はHTMLの仕様であるHTML Living Standardのメールアドレスのバリデーションに関する記載をみてみましょう。
HTMLの仕様であるHTML Living Standardにもメールアドレスのバリデーションに関する記載は、主にWHATWG(Web Hypertext Application Technology Working Group)のHTML Living Standard、MozillaのMDN Web Docsに記載があります。
HTML Living Standard のバリデーション方法
メールアドレスのバリデーションは、HTML Living Standardの「4.10.5.1.5 Email state (type=email)」に記載があり、以下の正規表現によることが分かります。
The following JavaScript- and Perl-compatible regular expression is an implementation of the above definition.
/^[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])?)*$/
この正規表現はRFC5321、RFC5322に準拠したものではありません。
This requirement is a willful violation of RFC 5322, which defines a syntax for email addresses that is simultaneously too strict (before the "@" character), too vague (after the "@" character), and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) to be of practical use here.
「This requirement is a willful violation of RFC 5322 (この要件は、RFC5322にあえて違反しています。)」とあるようにRFC5322とは異なっており、test..test@example.com
のようなRFCに違反したメールアドレスが弾かれないといったの違いがあります。
HTML Living Standard に準拠したバリデーションの問題点
HTML Living Standardの正規表現を利用するのが良さそうにみえますが、RFC5322とは異なるバリデーションとなる以上、問題もありますので、次でこのバリデーションの問題点をみていきましょう。
RFCに違反したメールアドレスが弾かれない
RFCに違反したメールアドレスが弾かれないということは利点であり、問題点でもあります。
SendGridなどのメール配信サービスを利用している場合、そもそも利用しているメール配信サービスの仕様に従う必要があり、メール配信サービスがRFC違反のメールアドレスを受け付けないのであれば、バリデーションで弾かないようにしても意味がありません。
SendGridではRFCに違反したメールアドレスそのままではメールは配信できませんが、以下のようにローカルパートをダブルクォーテーションで囲むことで、RFCに準拠した形式になり、メール送信処理ができるようになります。
test..test@example.com → "test..test"@example.com
つまり、バックエンド側でバリデーションチェックを行ったあと、さらにRFCに違反したメールアドレスかのチェックをし、RFC違反のメールアドレスであった場合は、ローカルパートをダブルクォーテーションで囲むようにするという手間が発生することとなります。
HTML Living Standard準拠のメールアドレスのバリデーションを採用する場合には、RFC5321、RFC5322に準拠しておけば生じなかった問題や手間が発生する可能性があるということをよく知っておくことが必要となります。
全角英数字などが使われていても弾かれる
こちらも利点であり、問題点でもあるといえます。
現時点では全角英数字などがメールアドレスに利用されることは、ほとんどありませんが、RFC6531にも
記載がある以上、今後増える可能性はありえます。
RFC6531準拠のメールアドレスが多くなってきたとき、全角英数字などをバリデーションで弾いてしまっては問題があります。正解は時代と共に変わることを常に意識しておくことが必要そうです。
HTML Living Standard によるバリデーションの実装
ここまでソースコードなしで説明してきましたので、ここでHTML Living Standard によるバリデーションの実装方法についても軽く触れておきます。
実装方法は言語やフレームワークによって異なりますが、TypeScriptやJavaScriptの場合は以下のようにtestメソッドやmatchメソッドを使ってバリデーションの実装をすることができます。
const emailValidation = (value: string): boolean => {
let regex = /^[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])?)*$/
if (regex.test(value)) {
return true;
} else {
return false;
}
}
ここではスラッシュ(/
)の前のバックスラッシュ(\
)はなくても問題ないため、省略していますが、HTML Living Standardの「4.10.5.1.5 Email state (type=email)」に記載のとおりとしても問題ありません。
実際の実装の一例としてvee-validate(Vue.jsのフォームライブラリ)を利用する場合については、以下のGitHubのリポジトリを参考にしてください。
email-validation-frontend
バリデーションの実装例
他の言語でも同じように正規表現によるバリデーションのチェックは実装可能です。
Javaの場合もMatcherクラスで同じように正規表現によるチェックを実装可能ですが、Javaの正規表現のチェックのための文字列ではバックスラッシュ(\
)のエスケープシーケンスとして\\
を使用する必要があるため注意が必要です。
String regex = "^[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])?)*$";
RFC準拠、HTML Living Standard準拠 共通の問題
さて、RFC準拠やHTML Living Standard準拠のメールアドレスのバリデーションをみてきましたが、両者共通の問題点はないのでしょうか?
実は両者共通の問題点もあります。
ドットレスドメインが弾かれない
ドットレスドメイン(Dotless Domain)とは、その名のとおり、test@example
のexample
部分のようにドットがないドメインです。
RFC5321、RFC5322の文書上では、このドットレスドメインのメールアドレスは使用可能であり、RFC準拠でもHTML Living Standard準拠でも、このドットレスドメインのメールアドレスは弾かれません。
しかしながら、2013年8月にICANNにおいて、このようなドットレスドメインの利用禁止が採択されているなどしており、通常は使用されません。これは、名前@所属のような文字列が、そのままメールアドレスとして認識されて、誤ってデータが送信されてしまうといったセキュリティ上の懸念があることなどに起因しています。
ドットレスドメインを弾きたい場合には、以下のようにアスタリスク(*
)をプラス(+
)に変えることで、「0回以上の繰り返し」から「1回以上の繰り返し」に変えることで対処可能となります。
/^[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])?)+$/
ユーザーにとって優しいバリデーションとは
RFC準拠のバリデーションにも、HTML Living Standard準拠のバリデーションにもそれぞれ利点と問題点があることがみえてきました。
では、どのようなバリデーションが*ユーザーにとって優しいバリデーションなのでしょうか…
正直に言うと正解は一つではないように思います。
たとえば、メールアドレス作成を行うようなサイトであれば、RFC5321、RFC5322準拠(RFC6531非準拠)で、かつドットレスドメインは認めないといった厳しい条件のバリデーションにしておくと、多くのサイトでそのメールアドレスが使用できないといった事象が回避できますので、ユーザーにとって優しいバリデーションと言えるかもしれません。
逆に自分が所持しているメールアドレスで会員登録を行うようなサイトでは、HTML Living Standard準拠のバリデーションにしておけば、現状のほとんどのメールアドレスが登録できますので、これがユーザーにとって優しいバリデーションと言えるかもしれません。(先述のとおり、メール配信サービスがRFC違反のメールアドレスに対応する方法があることなどが前提となります。)
まとめ
前項でユーザーにとって優しいバリデーションについて、自分の意見を記載しました。
しかしながら、これはあくまでも現時点(2024/12/17)での自分の意見となります。
すでにRFC違反のメールアドレスを使用している方は少なくなっており、これを無視しても問題ないのでは…と考えてもいますし、今後、RFC6531準拠のメールアドレスが増えてくれば、全角英数字や漢字、ひらがなを弾かないようなバリデーションにすべきではないか…とも考えています。
結局、自分がつくりたいサイトやアプリのメールアドレスの入力について、よく検討した上で、そのとき多く使用されているメールアドレスも分析・検討して、メールアドレスのバリデーションは考えないといけないということですね…
参考文献
RFC 5321 - Simple Mail Transfer Protocol
RFC 5322 - Internet Message Format
RFC 6531 - SMTP Extension for Internationalized Email
HTML Living Standard
<input type="email"> - HTML: ハイパーテキストマークアップ言語 | MDN
特殊な形式のアドレス(RFC違反アドレス)のご利用について | ドコモメール | サービス・機能 | NTTドコモ
【iPhone】auメール(@au.com/@ezweb.ne.jp)の送信ができません| よくあるご質問 | サポート | au
どういったメールアドレスに送信できますか? – サポート | SendGrid
インターネット用語1分解説~ドットレスドメイン名(Dotless Domain Names)とは~ - JPNIC
Discussion