メールアドレスを検証する方法を知っていました。 RFCを読むまで

翻訳者から: 記事を読んだ後、私はコメントで回答し始めましたが、私が参照するテキストは別の出版物にふさわしいと判断しました。 会いましょう!
電子メールアドレスの検証方法を知っている場合は、手を挙げてください。 手を挙げた人-誰かがあなたを見るまですぐに下げてください:手を離さないでキーボードに一人で座るのは愚かなことです。 私は比ly的に話した。



昨日まで、私も(形容的に)手を挙げていました。 サーバー上の電子メールアドレスの有効性を確認する必要がありました。 私はこれをすでに数十万回行っています(冗談ではありません-カウントします)。



今回、何らかの理由で、私は自分の仮定をもう一度理解するようになりました。 RFCの電子メールアドレスを読んだことがありません(ひっくり返すことすらありません)。 正しい電子メールアドレスが意味するものに基づいて実装を行っただけです。 まあ、あなたは彼らが通常誰が意味するかについて彼らが言うことを知っている [ perev。 著者は、 「あなたが仮定するとき、あなたあなたと私の を作る」-「あなたが(何か)を意味するとき、あなたは/を作ります。



そして、私は何か面白いものを見つけました。インターネット上で「電子メールアドレスの正確性をチェックする」と表示されるほとんどすべての正規表現は厳密すぎます。



電子メールアドレスのローカル部分(つまり、「@」記号の前)により、考えられるよりもはるかに多様な文字が使用できることがわかります。 SMTPを定義するRFC 2821のセクション2.3.10によると、「@」記号の前の部分はローカル部分(記号の後の部分は受信者ドメイン)と呼ばれ、受信者サーバーによって排他的に解釈されることを意図しています



その結果-そして、[addresses- transl。 ]を変更して転送を最適化しようとする中間ホストによって引き起こされる長い一連の問題のおかげです ]、 ローカル部分は、アドレスのドメイン部分で示されたサーバーによってのみ解釈されなければなりません(そして意味的な意味はそれに割り当てられるべきです)
RFC 2822の セクション3.4.1には、電子メールアドレスの仕様の詳細が説明されています(私- 著者が強調)。

アドレス指定は、ローカルで解釈される文字列を含むインターネット上の特定の識別子で、その後に「et」(「@」、ASCIIコード64)が続き、さらにインターネットドメインが続きます。 ローカルに解釈される文字列は、 引用符付き文字列またはポイントアトムです。
点アトムは、ドットで区切られた原子のコレクションです。 次に、 アトムは セクション3.2.4で英数字のセットとして定義され、次の文字のいずれかを含むことができます(ご存知のとおり、通常はマットに置き換えられます)...



! \$ & * - = ^ ` | ~ # % ' + / ? _ { }







さらに、ほぼすべての文字が有効なローカル部分を引用することは許可されています(推奨されず、めったに使用されません)。 引用符は、バックスラッシュ文字を使用するか、ローカル部分を二重引用符で囲むことにより実行できます。



RFC 3696 (名前の確認と変換のためのアプリケーション技術)は、SMTPプロトコル( RFC 2821 )の作成者が人間が読めるSMTP取扱説明書として作成しました。 3番目のセクションでは、有効な電子メールアドレスの例を示します。



これらは正しいメールアドレスです!





(私のお気に入りのバージョンのVasya Pupkinを使用したRFC作者への拍手-Joe Blow。)



さて、あなたの好きなバリデーターを通してそれらを実行してください。 さて、どれくらい過ぎましたか?



楽しみのために、正規表現を書いてみることにしました(おかげで、私はすでに通知を受けました。 今では2つの問題があります )。 ここにある。



^(?!\.)("([^"\r\\]|\\["\r\\])*"|([-a-z0-9!#$%&'*+/=?^_`{|}~] |(?@[a-z0-9][\w\.-]*[a-z0-9]\.[az][az\.]*[az]$







この式は、大文字と小文字の区別がオフになっていることを意味することに注意してください( .NETの RegexOptions.IgnoreCase )。 非常にい表現です。



私はそれがカバーするすべてのケースを実証するために単体テストを書きました。 各行にはメールアドレスとフラグが含まれています-正しいかどうか。



 [RowTest] [Row(@"NotAnEmail", false)] [Row(@"@NotAnEmail", false)] [Row(@"""test\\blah""@example.com", true)] [Row(@"""test\blah""@example.com", false)] [Row("\"test\\\rblah\"@example.com", true)] [Row("\"test\rblah\"@example.com", false)] [Row(@"""test\""blah""@example.com", true)] [Row(@"""test""blah""@example.com", false)] [Row(@"customer/department@example.com", true)] [Row(@"$A12345@example.com", true)] [Row(@"!def!xyz%abc@example.com", true)] [Row(@"_Yosemite.Sam@example.com", true)] [Row(@"~@example.com", true)] [Row(@".wooly@example.com", false)] [Row(@"wo..oly@example.com", false)] [Row(@"pootietang.@example.com", false)] [Row(@".@example.com", false)] [Row(@"""Austin@Powers""@example.com", true)] [Row(@"Ima.Fool@example.com", true)] [Row(@"""Ima.Fool""@example.com", true)] [Row(@"""Ima Fool""@example.com", true)] [Row(@"Ima Fool@example.com", false)] public void EmailTests(string email, bool expected) { string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[az][az\.]*[az]$"; Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); Assert.AreEqual(expected, regex.IsMatch(email) , "Problem with '" + email + "'. Expected " + expected + " but was not that."); }
      
      







あなたが私を恐ろしい退屈で退屈だと呼ぶ前に(あなたは正しいかもしれませんが、とにかく待ってください)、メールアドレスのそのような徹底的なチェックは絶対に必要だとは思いません。 ほとんどのメールプロバイダーには、より厳しいメール要件があります。 たとえば、Yahooの場合、文字で始まるアドレスが必要です。 ほとんどの電子メールプロバイダーが従う標準化された、より厳格なルールのセットがあるようですが、私が知る限り、どこにも文書化されていません。



phil.h\@\@ck@haacked.com



ようなメールアドレスを作成し、メールアドレスを必要とするがそのアドレスでアカウントを作成できないサイトでの技術サポートについて苦情を申し立て始めると思います。 いたずらが大好きです!



道徳は、偏見や仮定に時々挑戦することは有用であり、RFCに決して入らせないということです。



PS RFCを読んだときに犯したいくつかのエラーを修正しました。 ほら RFCを読んだ後でも、自分が何をしているのかまだわかりません。 プログラマーは読者ではないという主張をもう一度確認します



All Articles