note___つくる_つながる_とどける_

間違ったメールバリデーションが多いので正解を探してみた

1. 結論だけ知りたい!

以下の参考サイトのメールバリデーションを行えば、ほぼ問題ありません。
完全なバリデーションは難しいという私の結論です。
https://qiita.com/sakuro/items/1eaa307609ceaaf51123

2. メールバリデーションってなに?

メールアドレスが使用できるのか?の妥当性を確認することです。

使用できるのか?とは RFCに準拠しているか?になります。

3. RFCってなに?

メールアドレスに関するRFCは以下になります。
抜粋ですが、以下のセクションが参考になります。
読み解くのは大変ですが、完全なバリデーションは難しいです。

3.4.1. addr-spec 仕様
http://srgia.com/docs/rfc5322j.html#p3.4

addr-spec は具体的なインターネット識別子であり、ローカルで解釈される文字列の後にアットマーク("@" ASCII 値 64)、その後にインターネットドメイン名を持つ。ローカルで解釈される文字列は quoted-string または dot-atom のどちらかである。この文字列を dot-atom として表すことが可能な場合(つまり atext 文字の間に atext 文字か "." かだけを含む場合)には dot-atom 形式を使用するべき(SHOULD)であり、quoted-string 形式を使用するべきではない(SHOULD NOT)。"@" の前後にコメントや空白の折り返しを使用するべきではない(SHOULD)。
注意:ここに示されているのは addr-spec のドメイン部の寛容な文法である。ドメイン部は他のプロトコル(例えば [RFC1034], [RFC1035], [RFC1123], [RFC5321])で規定/使用されるアドレッシング情報を含む。そのため、それらが使用される状況に応じたアドレスの文法に従うことは、実装の責任である。
addr-spec       =   local-part "@" domain
local-part        =   dot-atom / quoted-string / obs-local-part
domain            =   dot-atom / domain-literal / obs-domain
domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
dtext                =   %d33-90 /          ; "[", "]", "\" を除く印刷可能な
                            %d94-126 /         ;   US-ASCII 文字
                            obs-dtext

3.2.3. アトム
http://srgia.com/docs/rfc5322j.html#p3.2.3



構造化ヘッダフィールド内に生成される内容のいくつかは、特定の基本的な文字からなる単純な文字列である。それらはアトムと呼ばれる。一部の構造化ヘッダフィールド本文は atext 内にピリオド("." ASCII 値 46)を許している。そのような目的のために追加の "dot-atom" トークンが定義されている。
注意:"specials" トークンはこの仕様には現れない。specials は atext 内に現れない単純な可視の(つまり非制御、非空白)文字である。これは、メッセージの字句解析を行うツールを使用する実装者にとって有用であるという理由で提供されているだけである。specials に含まれる各文字は字句解析におけるトークン化の位置を表すために使用できる。
atext           =   ALPHA / DIGIT /    ; Printable US-ASCII
             "!" / "#" /        ;  specials を除く文字
             "$" / "%" /        ;  atom に使用される
             "&" / "'" /
             "*" / "+" /
             "-" / "/" /
             "=" / "?" /
             "^" / "_" /
             "`" / "{" /
             "|" / "}" /
             "~"
atom            =   [CFWS] 1*atext [CFWS]
dot-atom-text   =   1*atext *("." 1*atext)
dot-atom        =   [CFWS] dot-atom-text [CFWS]
specials        =   "(" / ")" /        ; atext 内に現れない特殊文字
                  "<" / ">" /
                  "[" / "]" /
                  ":" / ";" /
                  "@" / "\" /
                  "," / "." /
                  DQUOTE
atom と dot-atom はともに、それを構成する文字列を含むひとつの構成単位として解釈される。残りの文字列の前後に置かれるオプションのコメントおよび FWS は意味的にアトムではない。アトムはアトム内の一連の atext 文字列、または dot-atom 内の atext と "." とだけである。

4. 有名どころのツールはRFCに準拠してるの?

しています。

sendgrid
https://support.sendgrid.kke.co.jp/hc/ja/articles/360000019762-どういったメールアドレスに送信できますか-

RFCに準拠したメールアドレスであれば基本的には送信できます。

Gmail
https://support.google.com/a/answer/6089246?hl=ja


Gmail での POP の仕組み
POP とはポストオフィス プロトコル(Post Office Protocol)の略で、Gmail のメールを Outlook、Thunderbird、Apple Mail などの互換性のあるメール クライアントと同期させるために使用されます。IMAP と同様、POP は Google が提供しているサービスではありません。POP は標準化された RFC 準拠のプロトコルで、どんなメールサービスやメール クライアントにも実装できます。

5. なぜ間違ったメールバリデーションが行われるの?(記事を書こうと思ったきっかけ)

その1:プログラム言語を習得するサイトのサンプルコードをコピペして使う人が多い

railsを習得するサイトだとRuby on rails Tutorialというサイトが有名かと思います。

そのサイトに以下のようなセクションがあります。

リスト 6.21: メールフォーマットを正規表現で検証する
https://railstutorial.jp/chapters/modeling_users?version=5.1#code-validates_format_of_email

class User < ApplicationRecord
 validates :name,  presence: true, length: { maximum: 50 }
 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
 validates :email, presence: true, length: { maximum: 255 },
                   format: { with: VALID_EMAIL_REGEX }
end

上記のような正規表現で検証されるメールアドレスはRFCに準拠より厳しい検証をしています。

その後、習得した人が実務でコーディングに入ります。

そうすると、メールアドレスを検証する機能を実装時に、そういえばあの覚えた正規表現使えるな!とそのまま流用(コピペ)してしまいます。

結果、間違ったメールバリデーションが行われてしまいます。

その2:ネット上に存在している情報が間違ってるものが上位に表示する

ネット上の情報表示順は、SEOで操作することができます。
操作できる情報の上位が正しいとは限りません

その3:QA時に正しい知識でテストを実施できていない

これは私自身の反省なんですが、メールアドレスの形式は@が途中にあればいいんでしょ?という思考停止でQAしておりました…。
この経験から私は、一次情報を探すようになりました。
以下のようなテストデータをまとめてくれるありがたい記事もあります。
https://qiita.com/yoshitake_1201/items/40268332cd23f67c504c

6. 間違った情報に惑わされないためにどうすれば良いの?

・記事に出典がある場合は必ず読みましょう。
・参考書やネット情報を鵜呑みにせずに、公式ドキュメント(一次情報)を読みましょう。
・サンプルコードはコピペするのではなくて、なぜそのロジックで動作するのかを考えましょう。

この記事が気に入ったらサポートをしてみませんか?