正規表現を使用してメールアドレスを検証する方法は?


3313

長年にわたり、サーバーの一部としてIPアドレスを使用しないことを前提として、MOSTメールアドレスを正しく検証する正規表現を徐々に開発してきました。

私はいくつかのPHPプログラムで使用しており、ほとんどの場合機能します。ただし、そのサイトを使用しているサイトで問題が発生し、調整をしなければならないという連絡が時々あります(最近では、4文字のTLDが許可されていないことに気付きました)。

メールの検証に使用した、または見た中で最も良い正規表現は何ですか?

いくつかの短い式を使用する関数を使用するいくつかのソリューションを見てきましたが、より複雑な関数のいくつかの短い式の代わりに、単純な関数の1つの長い複雑な式が欲しいです。



5
IDNAが正しくフォーマットされていることを検証できる正規表現は、stackexchangeに適合しません。(正規化のルールは本当に曲がりくねっていて、特に正規表現処理に不適切です)
Jasen


正規表現は可変である場合があり、電子メール詐欺はスペースを含むことができ、場合によってはスペースを含むことができません。
Ṃųỻịgǻňạcểơửṩ

回答:


2440

完全にRFC 822に準拠した正規表現は、その長さの非効率的かつ曖昧です。幸い、RFC 822は2回置き換えられ、電子メールアドレスの現在の仕様はRFC 5322です。RFC 5322は正規表現につながります。これは、数分間調べれば理解でき、実際の使用には十分効率的です。

1つのRFC 5322準拠の正規表現は、http://emailregex.com/のページの上部にありますが、インターネット内で浮動しているIPアドレスパターンを使用して00おり、ドット区切りのアドレス。これは違法です。残りの部分はRFC 5322の文法と一致しているようでgrep -Po、を使用して、ドメイン名、IPアドレス、不正なもの、引用符付きまたは引用符なしのアカウント名など、いくつかのテストに合格しています。

00IPパターンのバグを修正すると、正常に機能するかなり高速な正規表現が得られます。(実際のコードでは、マークダウンではなく、レンダリングされたバージョンをスクレイピングします。)

(?:[a-z0-9!#$%& '* + / =?^ _ `{|}〜-] +(?:\。[a-z0-9!#$%&' * + / =?^ _ `{|}〜-] +)* |"(?:[\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21 \ x23- \ x5b \ x5d- \ x7f] | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f])* ")@(?:(?:[a-z0-9](?:[a-z0-9-] * [a-z0 -9])?\。)+ [a-z0-9](?:[a-z0-9-] * [a-z0-9])?| \ [(?:(?:( 2(5 [0-5] | [0-4] [0-9])| 1 [0-9] [0-9] | [1-9]?[0-9]))\。){3}( ?:( 2(5 [0-5] | [0-4] [0-9])| 1 [0-9] [0-9] | [1-9]?[0-9])| [ a-z0-9-] * [a-z0-9]:(?:[\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21- \ x5a \ x53- \ x7f] | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f])+)\])

または:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

以下は、正規表現自体よりも明確な、上記の正規表現の 有限状態機械のですここに画像の説明を入力してください

PerlおよびPCRE(例えばPHPで使用される正規表現ライブラリ)のより洗練されたパターンは、RFC 5322を問題なく正しく解析できます。PythonとC#でも同じことができますが、最初の2つとは異なる構文を使用します。ただし、あまり強力でないパターンマッチング言語の1つを使用せざるを得ない場合は、実際のパーサーを使用するのが最善です。

また、RFCに従って検証しても、そのアドレスが実際に提供されたドメインに存在するかどうか、またはアドレスを入力した人が本当の所有者であるかどうかについてはまったく何もわからないことを理解することも重要です。人々はいつもこの方法でメーリングリストに他の人を登録しています。そのアドレスと同じWebページに入力するための確認トークンを含むメッセージをそのアドレスに送信することを含む、より洗練された種類の検証を必要とする修正。

確認トークンは、トークンを入力する人のアドレスを取得したことを確認する唯一の方法です。これが、現在ほとんどのメーリングリストがそのメカニズムを使用してサインアップを確認する理由です。結局のところ、誰でもを置くことができpresident@whitehouse.gov、それは合法であるとさえ解釈されますが、それは反対側の人である可能性は低いです。

PHPの場合、「PHPで電子メールアドレスを検証する」で説明したパターンを使用しないでください。

一般的な使用法と広範なずさんなコーディングにより、記録された正式な標準よりも厳しい電子メールアドレスの事実上の標準が確立されるといういくつかの危険があります。

これは、他のすべての非RFCパターンと同じです。RFC 5322は言うまでもなく、RFC 822を処理するのにも十分スマートではありません。しかし、これはそうです。

凝ったものにしたい場合は、完全な状態エンジンを実装してください。正規表現は、基本的なフィルターとしてのみ機能します。正規表現の問題は、正規表現で処理できないため、完全に有効な電子メールアドレスが無効(誤検知)であることを誰かに伝えることは、ユーザーの観点から見ると失礼で失礼です。目的の状態エンジンは、各RFCに従って電子メールアドレスを逆アセンブルするために無効と見なされる電子メールアドレスを検証し、修正することもできます。これにより、次のような潜在的により楽しい体験が可能になります

指定された電子メールアドレス 'myemail @ address、com'は無効です。「myemail@address.com」ですか?

コメントを含む電子メールアドレスの検証も参照してください。または、正規表現を検証する電子メールアドレスを比較します。

正規表現の可視化

Debuggexデモ


180
あなたは「良い正規表現はありません」と言った。これは一般的なものですか、それとも電子メールアドレス検証に固有のものですか。
Tomalak、2008年

37
@Tomalak:メールアドレスのみ。ボルツマイヤーが言ったように、RFCは非常に複雑です
Luk

37
あなたが言及したLinuxジャーナルの記事は、いくつかの点で事実上間違っています。特にLovellは明らかにRFC3696のエラッタを読んでおらず、RFCの公開されたバージョンのエラーのいくつかを繰り返しています。詳細:dominicsayers.com/isemail
ドミニクセイヤーズ

9
:ジェフ・アトウッドは、すべての有効な電子メールアドレスを検証するためにこのブログの記事で素敵な正規表現があるcodinghorror.com/blog/2005/02/regex-use-vs-regex-abuse.html
CMircea

5
現在のHTML5仕様には、電子メールタイプの入力検証用の正規表現とABNFが含まれており、元のRFCよりも意図的に制限されていることに注意しください。
シンクロ

747

メールアドレスの検証に正規表現を使用しないでください。

代わりに、次のようにMailAddressクラスを使用します。

try {
    address = new MailAddress(address).Address;
} catch(FormatException) {
    // address is invalid
}

このMailAddressクラスはBNFパーサーを使用して、RFC822に完全に準拠したアドレスを検証します。

を使用しMailAddressて電子メールアドレスを検証する場合は、このアプローチが電子メールアドレスの表示名部分も受け入れることに注意してください。これは、意図したとおりではない場合があることに注意してください。たとえば、次の文字列を有効な電子メールアドレスとして受け入れます。

  • 「user1@hotmail.com; user2@gmail.com」
  • 「user1@hotmail.com; user2@gmail.com; user3@company.com」
  • 「ユーザー表示名user3@company.com」
  • 「user4 @ company.com」

これらのケースの一部では、文字列の最後の部分のみがアドレスとして解析されます。その前の残りは表示名です。表示名のないプレーンな電子メールアドレスを取得するには、正規化されたアドレスを元の文字列と照合します。

bool isValid = false;

try
{
    MailAddress address = new MailAddress(emailAddress);
    isValid = (address.Address == emailAddress);
    // or
    // isValid = string.IsNullOrEmpty(address.DisplayName);
}
catch (FormatException)
{
    // address is invalid
}

さらに、user@company.MailAddressも同様に、末尾にドットが付いたアドレスを受け付けます。

あなたが本当に正規表現を使いたいなら、ここにあります:

(?:(?:\ r \ n)?[\ t])*(?:(?:(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031 ] +(?:(?:(?:\ r \ n)?[\ t]
)+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[^ \" \ r \\] | \\。 |(?:(?:\ r \ n)?[\ t]))* "(?:( ?:
\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\ \ "。\ [​​\] \ 000- \ 031] +(?:(?:(
?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[ ^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?[ 
\ t]))* "(?:(?:\ r \ n)?[\ t])*))* @(?:(?:\ r \ n)?[\ t])*(?: [^()<> @、;:\\ "。\ [​​\] \ 000- \ 0
31] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\ ]]))| \ [([^ \ [\] \ r \\] | \\。)* \
](?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^() <> @、;:\\ "。\ [​​\] \ 000- \ 031] +
(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]) )| \ [([^ \ [\] \ r \\] | \\。)* \](?:
(?:\ r \ n)?[\ t])*))* |(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?: (?:(?:\ r \ n)?[\ t])+ | \ Z
|(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[^ \" \ r \\] | \\。|(?:( ?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)
?[\ t])*)* \ <(?:(?:\ r \ n)?[\ t])*(?:@(?:[^()<> @、;:\\ "。 \ [\] \ 000- \ 031] +(?:(?:(?:\
r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\ ] \ r \\] | \\。)* \](?:(?:\ r \ n)?[
 \ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)
?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \ \] | \\。)* \](?:(?:\ r \ n)?[\ t]
)*))*(?:、@(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[
 \ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*
)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031 ] +(?:(?:(?:\ r \ n)?[\ t]
)+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\ 。)* \](?:(?:\ r \ n)?[\ t])*))*)
*:(?:(?:\ r \ n)?[\ t])*)?(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] + (?:(?:(?:\ r \ n)?[\ t])+
| \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[^ \" \ r \\] | \\。|( ?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r
\ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ " 。\ [\] \ 000- \ 031] +(?:(?:( ?:
\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?[\ t
]))* "(?:(?:\ r \ n)?[\ t])*))* @(?:(?:\ r \ n)?[\ t])*(?:[^ ()<> @、;:\\ "。\ [​​\] \ 000- \ 031
] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\] ]))| \ [([^ \ [\] \ r \\] | \\。)* \](
?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?
:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?
:\ r \ n)?[\ t])*))* \>(?:(?:\ r \ n)?[\ t])*)|(?:[^()<> @ ,; :\\ "。\ [​​\] \ 000- \ 031] +(?:(?
:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| "(? :[^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?
[\ t]))* "(?:(?:\ r \ n)?[\ t])*)*:(?:(?:\ r \ n)?[\ t])*(?: (?:(?:[^()<> @、;:\\ "。\ [​​\] 
\ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\" 。\ [\]]))| "(?:[^ \" \ r \\] |
\\。|(?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)?[\ t])*)(?:\。(? :(?:\ r \ n)?[\ t])*(?:[^()<>

@、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ [ "()<> @、;:\\"。\ [​​\]]))| "
(?:[^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))*"(?:(?:\ r \ n)?[ \ t])*))* @(?:(?:\ r \ n)?[\ t]
)*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t]) + | \ Z |(?= [\ ["()<> @、;:\\
"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])* )(?:\。(?:(?:\ r \ n)?[\ t])*(?
:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [
\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*))* | (?:[^()<> @、;:\\ "。\ [​​\] \ 000-
\ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [ \]]))| "(?:[^ \" \ r \\] | \\。|(
?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)?[\ t])*)* \ <(?:(?:\ r \ n)?[\ t])*(?:@(?:[^()<> @ ,;
:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["() <> @、;:\\ "。\ [​​\]]))| \ [([
^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "
。\ [\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、 ;:\\ "。\ [​​\]]))| \ [([^ \ [\
] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*))*(?:、@(?:(?:\ r \ n )?[\ t])*(?:[^()<> @、;:\\ "。\
[\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;: \\ "。\ [​​\]]))| \ [([^ \ [\] \
r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] 
\ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\" 。\ [\]]))| \ [([^ \ [\] \ r \\]
| \\。)* \](?:(?:\ r \ n)?[\ t])*))*)*:(?:(?:\ r \ n)?[\ t])* )?(?:[^()<> @、;:\\ "。\ [​​\] \ 0
00- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。 \ [\]]))| "(?:[^ \" \ r \\] | \\
。|(?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)?[\ t])*)(?:\。(?:( ?:\ r \ n)?[\ t])*(?:[^()<> @、
;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["( )<> @、;:\\ "。\ [​​\]]))|"(?
:[^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))*"(?:(?:\ r \ n)?[\ t ])*))* @(?:(?:\ r \ n)?[\ t])*
(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。
\ [\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*)( ?:\。(?:(?:\ r \ n)?[\ t])*(?:[
^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |( ?= [\ ["()<> @、;:\\"。\ [​​\]
]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*))* \>( ?:(?:\ r \ n)?[\ t])*)(?:、\ s *(
?:(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t]) + | \ Z |(?= [\ ["()<> @、;:\\
"。\ [​​\]]))|"(?:[^ \ "\ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))*"(? :(?:\ r \ n)?[\ t])*)(?:\。(?:(
?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(? :\ r \ n)?[\ t])+ | \ Z |(?= [
\ ["()<> @、;:\\"。\ [​​\]]))| "(?:[^ \" \ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)?[\ t
])*))* @(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t
])+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \ \。)* \](?:(?:\ r \ n)?[\ t])*)(?
:\。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +( ?:(?:(?:\ r \ n)?[\ t])+ |
\ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*))* |(?:
[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z | (?= [\ ["()<> @、;:\\"。\ [​​\
]]))| "(?:[^ \" \ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))* "(?:(?:\ r \ n)?[\ t])*)* \ <(?:(?:\ r \ n)
?[\ t])*(?:@(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["
()<> @、;:\\ "。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)
?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)? [\ t])+ | \ Z |(?= [\ ["()<>

@、;:\\ "。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)? [\ t])*))*(?:、@(?:(?:\ r \ n)?[
 \ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、
;:\\ "。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])*)(?:\。(?:(?:\ r \ n)?[\ t]
)*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t]) + | \ Z |(?= [\ ["()<> @、;:\\
"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \](?:(?:\ r \ n)?[\ t])* ))*)*:(?:(?:\ r \ n)?[\ t])*)?
(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ ["()<> @、;:\\"。
\ [\]]))| "(?:[^ \" \ r \\] | \\。|(?:(?:\ r \ n)?[\ t]))* "(?:( ?:\ r \ n)?[\ t])*)(?:\。(?:( ?:
\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])+ | \ Z |(?= [\ [
"()<> @、;:\\"。\ [​​\]]))| "(?:[^ \" \ r \\] | \\。|(?:(?:\ r \ n) ?[\ t]))* "(?:(?:\ r \ n)?[\ t])
*))* @(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?:(?:(?:\ r \ n)?[\ t])
+ | \ Z |(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。 )* \](?:(?:\ r \ n)?[\ t])*)(?:\
。(?:(?:\ r \ n)?[\ t])*(?:[^()<> @、;:\\ "。\ [​​\] \ 000- \ 031] +(?: (?:(?:\ r \ n)?[\ t])+ | \ Z
|(?= [\ ["()<> @、;:\\"。\ [​​\]]))| \ [([^ \ [\] \ r \\] | \\。)* \] (?:(?:\ r \ n)?[\ t])*))* \>(?:(
?:\ r \ n)?[\ t])*))*)?; \ s *)

26
.NET 4.0のMailAddressクラスは、以前のバージョンよりも電子メールアドレスの検証に優れていることがわかります。私はいくつかの重要な改善を行いました。
ジェフタッカー

7
私はそれは一種の...機能しないと思います...より単純なIDでは... a @ bは検証しません。ar@b.comはar @ bまでのみ一致し、.comは一致しません。ただし、「I am me」@ [10.10.10.10]のように機能します。:)
Raze

5
これらのRFC準拠の正規表現バリデーターは、「a <body / onload = alert( ' lol.com? ' +document.cookies)@aa>のように、おそらく受け入れたくない多くのメールアドレスを通過させることに注意してください。"これはperlのEmail :: Valid(その巨大な正規表現を使用)の有効なメールアドレスであり、XSS rt.cpan.org/Public/Bug/Display.html?id=75650
Matthew Lock

9
@MatthewLock:それは最悪ですfake@not-a-real-domain.name。XSSを防ぐために、電子メールの検証に依存することはできません
SLaks '28

10
@MatthewLock:いいえ。SQLクエリをエスケープする必要があります(または、さらに良いことに、パラメータを使用します)。消毒は適切な防御ではありません。
SLaks 2016年

536

この質問は頻繁に寄せられますが、メールアドレスを構文的に検証する理由を一歩踏み込んで考えるべきでしょうか。本当にメリットは何ですか?

  • 一般的なタイプミスは検出されません。
  • 無効なメールアドレスや偽のメールアドレスを入力したり、他人のアドレスを入力したりするのを防ぐことはできません。

メールが正しいことを検証する場合は、確認メールを送信してユーザーに返信する以外に選択肢はありません。多くの場合、あなたがします持っているセキュリティ上の理由や倫理的な理由のために、とにかく確認メールを送信するために(そうすることができます彼らの意思に反してサービスまでありません例えばサイン誰かが)。


92
単純な間違いを見つけるためだけに、クライアント側の検証でフィールドにsome @ somethingを入力したことを確認することは価値があるかもしれませんが、一般的には正しいです。
マーティンベケット

8
マーティン、私はあなたに+1を与えましたが、foobar @ dkは有効なメールであることを後で読むためにだけです。きれいではありませんが、RFCに準拠し、常識を使いたい場合は、このようなケースを検出し、ユーザーに正しいことを確認するよう依頼してください。
philfreo 2009

106
@olavk:誰かがタイプミス(例:)を入力した場合me@hotmail、確認メールが届かないことは明らかです。彼らはあなたのサイトにもういないので、なぜ彼らはサインアップできなかったのかと思っています。実際、彼らはそうではありません-彼らはあなたのことを完全に忘れてしまいました。ただし、正規表現を使用して基本的な健全性チェックを行うことができれば、すぐにそのエラーをキャッチして、ユーザーを満足させることができます。
nickf

5
@JacquesB:あなたは素晴らしいことを言っています。それがRFCごとにマスターを渡すからといって、それが実際にそのユーザーのアドレスであるとは限りません。それ以外の場合、これらのpresident@whitehouse.govアドレスはすべて非常にnetbusyの最高司令官を示しています。:)
tchrist 2010年

39
黒または白である必要はありません。電子メールが間違っているように見える場合は、ユーザーにそのことを知らせてください。それでもユーザーが続行したい場合は、許可してください。ユーザーに正規表現への準拠を強制するのではなく、正規表現をツールとして使用して、間違いがある可能性があることをユーザーに知らせます。
忍者14

354

それはすべてあなたがなりたい精度に依存します。私の目的のために、bob @ aol.com(メールのスペース)やsteve(ドメインなし)やmary@aolcom(.comの前のピリオドなし)のようなものを締め出そうとしているだけですが、

/^\S+@\S+\.\S+$/

もちろん、それは有効なメールアドレスではないものと一致しますが、それは一般的な単純なエラーを取得する問題です。

その正規表現に加えられる変更はいくつもありますが(一部はこの回答のコメントにあります)、それは単純で、理解しやすく、最初の試みとしてはすばらしいものです。


6
それは有効と作業メールアドレスであるfoob​​arに@ DKと一致していない(おそらく、ほとんどのメールサーバがそれを受け入れないだろうかsomething.comを追加しますが。)
bortzmeyer

3
はい、そうです。自分で試してみることをお勧めします。$ perl -le'print q{foo@bar.co.uk} =〜/^\S+@\S+\.\S+$/?q {Y}:q {N} '
アンディレスター

7
@Richard: .に含まれてい\Sます。
David Thornley、

43
JJJ:はい、それは多くのがらくたと一致します。それは&$ *#$(@ $ 0(%))$#。)&*)(* $にも一致します。私にとって、mary@aolcom私は完全なゴミであるような奇妙な指の誤植をキャッチすることにもっと関心があります。。YMMV。
アンディ・レスター

5
@看板を操作するためだけに:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/ jsfiddle.net/b9chris/mXB96
Chris Moschini 14

338

それはあなたが何を意味するかによります:すべての有効なメールアドレスをキャッチすることについて話している場合は、以下を使用してください:

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
 \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
 \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
 \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)

http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html)より簡単なものを探しているが、ほとんどの有効な電子メールアドレスを検出できる場合は、次のようにします。

"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"

編集:リンクから:

この正規表現は、コメントが取り除かれ、空白で置き換えられたアドレスのみを検証します(これはモジュールによって行われます)。


10
すべてのアドレスに一致するわけではありません。最初に変換する必要があるものもあります。リンクから:「この正規表現は、コメントが取り除かれ、空白で置き換えられたアドレスのみを検証します(これはモジュールによって行われます)。」
Chas。オーウェンズ

47
email address2番目のものを誤って通過するものの、長い正規表現に引っ掛かっている例を教えてください。
Lazer、

4
私はかつてそれを気に入っていましたが、それはRFC 822バリデーターであり、RFC 5322バリデーターではありません。
tchrist 2010年

24
@Lazer in..valid @ example.comは簡単な例です。ローカル部分に、引用符で囲まれていない2つのドットを続けることはできません。
ランダルシュワルツ

5
@Mikhail perlですが、実際には使用しないでください。
善人

287

[更新]私はここで電子メールアドレスの検証について知っているすべてを照合しました:http : //isemail.infoは、電子メールアドレスの検証だけでなく、診断も行います。検証は答えの一部にすぎないという、ここでのコメントの多くに同意します。http://isemail.info/aboutで私のエッセイを参照してください。

is_email()は、私が知る限り、特定の文字列が有効な電子メールアドレスであるかどうかを明確に通知する唯一のバリデーターです。http://isemail.info/で新しいバージョンをアップロードしました

Cal Henderson、Dave Child、Phil Haack、Doug Lovell、RFC5322、RFC 3696のテストケースを照合しました。全部で275のテストアドレス。私はこれらすべてのテストを、見つけたすべての無料のバリデーターに対して実行しました。

人々がバリデーターを強化している間、私はこのページを最新の状態に保つよう努めます。Cal、Michael、Dave、Paul、Philは、これらのテストのコンパイルおよび私の検証者の建設的な批判に対する協力と協力に感謝します。

特にRFC 3696に対するエラッタに注意する必要があります。正規の3つの例は、実際には無効なアドレスです。また、アドレスの最大長は、320 ではなく 254または256文字です。


このバリデーターも正しいようです。[...時間が経過しました...]うーん、それは単なるRFC 5322であり、3693やエラッタではないようです。
tchrist 2010年

1
非常に素晴らしい。ここでは、優れたエッセイを入手できるだけでなく、検証テスターとダウンロードするライブラリも入手できます。いい答えだ!
bgmCoder 2013

バリデーターはpunycode(RFC 3492)をサポートしていません。name@öäü.atは有効なアドレスにすることができます。(これはname@xn--4ca9at.atに変換されます)
ジョセフは、モニカ

@Josefさん、こんにちは。name@xn--4ca9at.atこのコードは解釈ではなく検証に関するものなので、検証を試みる必要があります。あなたがPunycodeでの翻訳を追加したい場合は、私がでプル要求を受け入れるように幸せgithub.com/dominicsayers/isemail
ドミニク・セイヤーズ

266

パーW3C HTML5仕様

^[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])?)*$

環境:

有効な電子メールアドレスは、 ABNF生産[...]を一致する文字列です。

注:この要件は、RFC 5322の意図的な違反です。RFC5322は、電子メールアドレスの構文が厳密すぎ(「@」文字の前)、曖昧すぎ(「@」文字の後ろ)、緩い(ここでは、コメント、空白文字、引用符付き文字列をほとんどのユーザーに馴染みのない方法で使用できるようにします。

次のJavaScriptおよびPerl互換の正規表現は、上記の定義の実装です。

/^[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])?)*$/


12
これは面白い。これはRFCの違反ですが、意図的なものであり、それはssneになります。実際の例:Gmailは@の前の部分のドットを無視するため、メールがtest@gmail.comの場合、test。@ gmail.comまたはtest .... @ gmail.comにメールを送信できます。これらのアドレスは両方ともRFCによると無効ですが、実際には有効です。
バレンティーナ2013年

最後の部分は「*」ではなく「+」にする必要があると思います:^ [a-zA-Z0-9。!#$%& '* + / =?^ _ `{|}〜-] + @ [a- zA-Z0-9-] +(?:\。[a-zA-
Z0-9-

7
@mmmmmm john.doe@localhostは有効です。確かに、実際のアプリケーション(つまり、コミュニティ)では、*を+に置き換えることをお勧めします
rabudde

3
@valentinas実際、RFCはこれらのローカル部分を排除していませが、引用する必要があります。"test...."@gmail.comRFCによれば完全に有効であり、意味的にはと同等test....@gmail.comです。
リンケ2014年

。@または.. @のアドレスに送信しようとすると、会社のリレーを介してpythonを使用してメールを送信しようとするとエラーが発生します。実際、_ @の場合も同様です。送信する前に、受信者が実行することを信頼するよりも削除します。
ndvo 2016

201

Perl 5.10以降では簡単です。

/(?(DEFINE)
   (?<address>         (?&mailbox) | (?&group))
   (?<mailbox>         (?&name_addr) | (?&addr_spec))
   (?<name_addr>       (?&display_name)? (?&angle_addr))
   (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
   (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ;
                                          (?&CFWS)?)
   (?<display_name>    (?&phrase))
   (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

   (?<addr_spec>       (?&local_part) \@ (?&domain))
   (?<local_part>      (?&dot_atom) | (?&quoted_string))
   (?<domain>          (?&dot_atom) | (?&domain_literal))
   (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                 \] (?&CFWS)?)
   (?<dcontent>        (?&dtext) | (?&quoted_pair))
   (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

   (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
   (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
   (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
   (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

   (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
   (?<quoted_pair>     \\ (?&text))

   (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
   (?<qcontent>        (?&qtext) | (?&quoted_pair))
   (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                        (?&FWS)? (?&DQUOTE) (?&CFWS)?)

   (?<word>            (?&atom) | (?&quoted_string))
   (?<phrase>          (?&word)+)

   # Folding white space
   (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
   (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
   (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
   (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
   (?<CFWS>            (?: (?&FWS)? (?&comment))*
                       (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

   # No whitespace control
   (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

   (?<ALPHA>           [A-Za-z])
   (?<DIGIT>           [0-9])
   (?<CRLF>            \x0d \x0a)
   (?<DQUOTE>          ")
   (?<WSP>             [\x20\x09])
 )

 (?&address)/x

20
これをPythonで見たい
tdc '15

4
そのaddrspec部分の一部だけが本当に質問に関係があると思います。RFC5822の完全なアドレスを受け入れる準備ができていないシステムの他の部分は、自分の足で撮影するようなものですが、それ以上を受け入れて転送します。
ドルメン

3
素晴らしい(+1)ですが、技術的にはもちろん正規表現ではありません...(文法が規則的でないため不可能です)。
Rinke

10
regexesはしばらく前に正規でなくなった。しかし、これは有効なPerlの「正規表現」です。
rjh 2014年

4
IDEoneでこの正規表現のテストを設定しました:ideone.com/2XFecHただし、「完全に」公平ではありません。誰かがチャイムを鳴らしたいと思いますか?何か不足していますか?
マイク14

159

私が使う

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

これは、ASP.NETでRegularExpressionValidatorによって使用されるものです。


28
ブー!私の(よく知られていない)アドレス!@mydomain.netが拒否されました。
Phrogz

3
このページによると、data.iana.org / TLD / tlds-alpha-by-domain.txtには、最上位に1文字のみのドメインはありません。例:「something.c」、「something.a」、ここにバージョン少なくとも2文字をサポート:「something.pl」、「something.us」:^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
Tomasz Szulc '19 / 11/19

4
@Wayne Whitty。メール検証をテストする場合を除いて、誰も使用しないアドレスも含めて、アドレスの大部分に対応するか、それともALLにするかという主要な問題に直面しました。
Patanjali 2015年

@TomaszSzulc回答の余分なバックスラッシュは混乱を招くので、修正しました。2文字のドメイン名のサポートが機能しています。^ \ w +([-+。 '] \ w +)* @ \ w +([-。] \ w +)* \。\ w {2、}([-。] \ w +)* $
Aqib Mumtaz

2
これは失敗しsimon-@hotmail.com、実際に有効です(私たちの顧客は同様の住所を持っています) `
Simon_Weaver

142

最善の方法についてはわかりませんが、アドレスのコメントが削除され、空白で置き換えられている限り、これは少なくとも正しいものです。

真剣に。メールの検証には、すでに作成されているライブラリを使用する必要があります。最善の方法は、おそらく確認メールをそのアドレスに送信することです。


2
私の知る限り、一部のライブラリも間違っています。PHP PEARにはそのようなバグがあったことを漠然と覚えています。
bortzmeyer 2008年

また、このページの下部には、仕様の2つの事項に関する免責事項があります。正規表現がサポートしていないこと。
Chris Vest、

7
これはRFC 5322仕様ではなく、RFC 822 仕様です。
tchrist 2010年

12
結局のところ、電子メールアドレスを本当に検証する唯一の方法は、電子メールアドレスに電子メールを送信して返信を待つことであるという点で、彼は正しいです。
Blazemonger、2011年

109

検証する電子メールアドレスは、System.Net.Mail名前空間を使用してASP.NET Webアプリケーションで使用され、ユーザーのリストに電子メールを送信します。そのため、非常に複雑な正規表現を使用するのではなく、アドレスからMailAddressインスタンスを作成しようとしています。MailAddressコンストラクタは、アドレスが適切に形成されていない場合に例外をスローします。このようにして、少なくともメールをドアの外に出すことができます。もちろん、これはサーバー側の検証ですが、とにかく最低限必要です。

protected void emailValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
    try
    {
        var a = new MailAddress(txtEmail.Text);
    }
    catch (Exception ex)
    {
        args.IsValid = false;
        emailValidator.ErrorMessage = "email: " + ex.Message;
    }
}

3
良い点。このサーバーの検証で一部の有効なアドレスが拒否された場合でも、この特定のサーバーテクノロジーを使用してこのアドレスに送信することはできないため、問題にはなりません。または、デフォルトのツールの代わりに、使用するサードパーティのメールライブラリを使用して同じことを試すこともできます。
ユーザー

私はこれが.Netフレームワークコードをどのように活用するかを本当に気に入っています。これは素晴らしいです。シンプルでクリーンで、実際にメールを送信できることを保証します。すごい仕事。
Cory House

...はい、検証方法に関心がある人は、Reflectorのコードを確認してください。かなりの部分があり、正規表現ではありません。
トムカーター

2
注:MailAddressクラスは、RFC5322と一致しません。これを検証に使用するだけの場合(および送信しない場合は、上記のように問題点です)。参照:stackoverflow.com/questions/6023589/...は
porges

ちょっとした問題:サーバー側の検証コードを再利用可能にしたい場合(この場合または一般的に)、ハードコードされargs.Valueたフィールドを参照する代わりに使用することをお勧めしますtxtEmail.Text。後者は単一のコントロールインスタンスにバリデーターをバインドします。単一の電子メールフィールドがある限り問題はありませんが、それ以外の場合はお勧めしません。
ホルパー

109

素早い回答

入力検証には次の正規表現を使用します。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+

この正規表現に一致するアドレス:

  • RFC 5321/5322に厳密に準拠しているローカル部分(つまり、@記号の前の部分)がある。
  • 少なくとも2つのラベルが付いたホスト名であるドメイン部分(つまり、@記号の後の部分)があり、各ラベルの長さが最大63文字である。

2番目の制約は、RFC 5321/5322の制限です。

精巧な答え

電子メールアドレスを認識する正規表現を使用すると、さまざまな状況で役立ちます。たとえば、ドキュメント内の電子メールアドレスをスキャンしたり、ユーザー入力を検証したり、データリポジトリの整合性制約として使用したりできます。

ただし、アドレスが実際に既存のメールボックスを参照しているかどうかを確認したい場合は、そのアドレスにメッセージを送信する以外に方法はありません。アドレスが文法的に正しいかどうかだけを確認したい場合は、正規表現を使用できますが、これ""@[]は文法的に正しいメールアドレスであり、既存のメールボックスを参照しないことに注意してください。

電子メールアドレスの構文は、さまざまなRFC、特にRFC 822RFC 5322で定義されています。RFC 822は「元の」標準と見なされ、RFC 5322は最新の標準と見なされます。RFC 822で定義された構文は最も寛容であり、後続の標準によって構文がますます制限されています。新しいシステムまたはサービスは古い構文を認識しますが、生成することはありません。

この回答では、「電子メールアドレス」をaddr-specRFCで定義されているとおり(つまりjdoe@example.org"John Doe"<jdoe@example.org>ではなくsome-group:jdoe@example.org,mrx@exampel.org;)と解釈します。

RFC構文を正規表現に変換することには1つの問題があります。構文は規則的ではありません!これは、無限にネストできる電子メールアドレスにオプションのコメントを許可するためです。一方、無限のネストは正規表現では記述できません。コメントを含むアドレスをスキャンまたは検証するには、パーサーまたはより強力な式が必要です。(Perlのような言語には、文脈自由文法を正規表現のように記述するための構成要素があることに注意してください。)この回答では、コメントは無視し、適切な正規表現のみを考慮します。

RFCは、電子メールメッセージ自体の構文ではなく、電子メールメッセージの構文を定義します。アドレスはさまざまなヘッダーフィールドに表示される場合があり、ここで主に定義されます。ヘッダーフィールドに表示される場合、アドレスには(字句トークン間で)空白、コメント、改行が含まれる場合があります。しかし、意味的にこれは重要ではありません。この空白などをアドレスから削除すると、意味的に同等の正規表現が得られます。したがって、の正規表現はfirst. last (comment) @ [3.5.7.9]ですfirst.last@[3.5.7.9]

さまざまな構文をさまざまな目的に使用する必要があります。(おそらく非常に古い)ドキュメントの電子メールアドレスをスキャンする場合は、RFC 822で定義されている構文を使用することをお勧めします。一方、ユーザー入力を検証する場合は、 RFC 5322で定義されている構文、おそらく正規表現のみを受け入れます。特定のケースに適用する構文を決定する必要があります。

この回答では、ASCII互換の文字セットを想定して、POSIXの「拡張」正規表現を使用しています。

RFC 822

次の正規表現にたどり着きました。私はそれを試して壊すようにみんなを招待します。誤検知や誤検知が見つかった場合は、コメントに投稿してください。できるだけ早く修正できるよう努めます。

([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*

エラータを含むRFC 822に完全に準拠していると思います。正規形式のメールアドレスのみを認識します。空白を認識する(折りたたむ)正規表現については、以下の派生を参照してください。

派生は、どのようにして式に到達したかを示しています。RFCの関連するすべての文法規則を、表示されているとおりにリストし、その後に対応する正規表現を続けます。エラータが公開されている場合は、修正された文法規則(「エラータ」とマークされている)に別の式を指定し、後続の正規表現でサブ表現として更新バージョンを使用します。

3.1.4項で述べたとおり。RFC 822のオプションの線形空白を字句トークンの間に挿入できます。該当する場合は、このルールに対応するように式を拡張し、結果を「opt-lwsp」でマークしました。

CHAR        =  <any ASCII character>
            =~ .

CTL         =  <any ASCII control character and DEL>
            =~ [\x00-\x1F\x7F]

CR          =  <ASCII CR, carriage return>
            =~ \r

LF          =  <ASCII LF, linefeed>
            =~ \n

SPACE       =  <ASCII SP, space>
            =~  

HTAB        =  <ASCII HT, horizontal-tab>
            =~ \t

<">         =  <ASCII quote mark>
            =~ "

CRLF        =  CR LF
            =~ \r\n

LWSP-char   =  SPACE / HTAB
            =~ [ \t]

linear-white-space =  1*([CRLF] LWSP-char)
                   =~ ((\r\n)?[ \t])+

specials    =  "(" / ")" / "<" / ">" / "@" /  "," / ";" / ":" / "\" / <"> /  "." / "[" / "]"
            =~ [][()<>@,;:\\".]

quoted-pair =  "\" CHAR
            =~ \\.

qtext       =  <any CHAR excepting <">, "\" & CR, and including linear-white-space>
            =~ [^"\\\r]|((\r\n)?[ \t])+

dtext       =  <any CHAR excluding "[", "]", "\" & CR, & including linear-white-space>
            =~ [^][\\\r]|((\r\n)?[ \t])+

quoted-string  =  <"> *(qtext|quoted-pair) <">
               =~ "([^"\\\r]|((\r\n)?[ \t])|\\.)*"
(erratum)      =~ "(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-literal =  "[" *(dtext|quoted-pair) "]"
               =~ \[([^][\\\r]|((\r\n)?[ \t])|\\.)*]
(erratum)      =~ \[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

atom        =  1*<any CHAR except specials, SPACE and CTLs>
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+

word        =  atom / quoted-string
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-ref  =  atom

sub-domain  =  domain-ref / domain-literal
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

local-part  =  word *("." word)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*

domain      =  sub-domain *("." sub-domain)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*

addr-spec   =  local-part "@" domain
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*(\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*)*@((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(canonical) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*

RFC 5322

次の正規表現にたどり着きました。私はそれを試して壊すようにみんなを招待します。誤検知や誤検知が見つかった場合は、コメントに投稿してください。できるだけ早く修正できるよう努めます。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])

エラータを含むRFC 5322に完全に準拠していると思います。正規形式のメールアドレスのみを認識します。空白を認識する(折りたたむ)正規表現については、以下の派生を参照してください。

派生は、どのようにして式に到達したかを示しています。RFCの関連するすべての文法規則を、表示されているとおりにリストし、その後に対応する正規表現を続けます。意味的に無関係な(折りたたみ)空白を含むルールの場合、この空白を受け入れない「(正規化)」とマークされた別の正規表現を指定します。

RFCの「obs-」ルールをすべて無視しました。これは、正規表現がRFC 5322に厳密に準拠している電子メールアドレスにのみ一致することを意味します。(「obs-」ルールを含むより緩い文法のように)「古い」アドレスを一致させる必要がある場合は、前の段落のRFC 822正規表現のいずれかを使用できます。

VCHAR           =   %x21-7E
                =~  [!-~]

ALPHA           =   %x41-5A / %x61-7A
                =~  [A-Za-z]

DIGIT           =   %x30-39
                =~  [0-9]

HTAB            =   %x09
                =~  \t

CR              =   %x0D
                =~  \r

LF              =   %x0A
                =~  \n

SP              =   %x20
                =~  

DQUOTE          =   %x22
                =~  "

CRLF            =   CR LF
                =~  \r\n

WSP             =   SP / HTAB
                =~  [\t ]

quoted-pair     =   "\" (VCHAR / WSP)
                =~  \\[\t -~]

FWS             =   ([*WSP CRLF] 1*WSP)
                =~  ([\t ]*\r\n)?[\t ]+

ctext           =   %d33-39 / %d42-91 / %d93-126
                =~  []!-'*-[^-~]

("comment" is left out in the regex)
ccontent        =   ctext / quoted-pair / comment
                =~  []!-'*-[^-~]|(\\[\t -~])

(not regular)
comment         =   "(" *([FWS] ccontent) [FWS] ")"

(is equivalent to FWS when leaving out comments)
CFWS            =   (1*([FWS] comment) [FWS]) / FWS
                =~  ([\t ]*\r\n)?[\t ]+

atext           =   ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
                =~  [-!#-'*+/-9=?A-Z^-~]

dot-atom-text   =   1*atext *("." 1*atext)
                =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

dot-atom        =   [CFWS] dot-atom-text [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

qtext           =   %d33 / %d35-91 / %d93-126
                =~  []!#-[^-~]

qcontent        =   qtext / quoted-pair
                =~  []!#-[^-~]|(\\[\t -~])

(erratum)
quoted-string   =   [CFWS] DQUOTE ((1*([FWS] qcontent) [FWS]) / FWS) DQUOTE [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  "([]!#-[^-~ \t]|(\\[\t -~]))+"

dtext           =   %d33-90 / %d94-126
                =~  [!-Z^-~]

domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  \[[\t -Z^-~]*]

local-part      =   dot-atom / quoted-string
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+"

domain          =   dot-atom / domain-literal
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*]

addr-spec       =   local-part "@" domain
                =~  ((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?)@((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?)
(normalized)    =~  ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])

一部のソース(特にw3c)は、RFC 5322がローカル部分(つまり、@記号の前の部分)に対して厳しすぎると主張していることに注意してください。これは、「..」、「a..b」、「a。」が原因です。それらはメールボックス名として使用される可能性がありますが、有効なドットアトムではありません。RFCは、しかし、ないそれらが引用されたことをしていることを除いて、これらのような地元の部品を可能にします。だからa..b@example.netあなたの代わりにを書くべきです"a..b"@example.net、これは意味的に同等です。

さらなる制限

SMTP(RFC 5321で定義)は、有効な電子メールアドレス(または実際にはメールボックス名)のセットをさらに制限します。このより厳密な文法を課すことは合理的であるように思われます。そのため、一致した電子メールアドレスを実際に使用して電子メールを送信できます。

RFC 5321は基本的に「ローカル」の部分(つまり、@記号の前の部分)をそのままにしますが、ドメイン部分(つまり、@記号の後の部分)に厳密です。ドットアトムの代わりにホスト名、ドメインリテラルの代わりにアドレスリテラルのみを許可します。

RFC 5321で提示されている文法は、ホスト名とIPアドレスの両方に関してはあまりにも寛大です。このドラフトRFC 1034をガイドラインとして使用して、問題のルールを自由に「修正」しました。これが結果の正規表現です。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])

ユースケースによっては、正規表現で「General-address-literal」を許可したくない場合があることに注意してください。また(?!IPv6:)、最終的な正規表現で否定先読みを使用して、「General-address-literal」の部分が不正な形式のIPv6アドレスと一致しないようにしました。一部の正規表現プロセッサは否定先読みをサポートしていません。|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+「General-address-literal」部分全体を削除する場合は、正規表現から部分文字列を削除してください。

ここに派生があります:

Let-dig         =   ALPHA / DIGIT
                =~  [0-9A-Za-z]

Ldh-str         =   *( ALPHA / DIGIT / "-" ) Let-dig
                =~  [0-9A-Za-z-]*[0-9A-Za-z]

(regex is updated to make sure sub-domains are max. 63 charactes long - RFC 1034 section 3.5)
sub-domain      =   Let-dig [Ldh-str]
                =~  [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?

Domain          =   sub-domain *("." sub-domain)
                =~  [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*

Snum            =   1*3DIGIT
                =~  [0-9]{1,3}

(suggested replacement for "Snum")
ip4-octet       =   DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35
                =~  25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]

IPv4-address-literal    =   Snum 3("."  Snum)
                        =~  [0-9]{1,3}(\.[0-9]{1,3}){3}

(suggested replacement for "IPv4-address-literal")
ip4-address     =   ip4-octet 3("." ip4-octet)
                =~  (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}

(suggested replacement for "IPv6-hex")
ip6-h16         =   "0" / ( (%x49-57 / %x65-70 /%x97-102) 0*3(%x48-57 / %x65-70 /%x97-102) )
                =~  0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}

(not from RFC)
ls32            =   ip6-h16 ":" ip6-h16 / ip4-address
                =~  (0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}

(suggested replacement of "IPv6-addr")
ip6-address     =                                      6(ip6-h16 ":") ls32
                    /                             "::" 5(ip6-h16 ":") ls32
                    / [                 ip6-h16 ] "::" 4(ip6-h16 ":") ls32
                    / [ *1(ip6-h16 ":") ip6-h16 ] "::" 3(ip6-h16 ":") ls32
                    / [ *2(ip6-h16 ":") ip6-h16 ] "::" 2(ip6-h16 ":") ls32
                    / [ *3(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16 ":"  ls32
                    / [ *4(ip6-h16 ":") ip6-h16 ] "::"                ls32
                    / [ *5(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16
                    / [ *6(ip6-h16 ":") ip6-h16 ] "::"
                =~  (((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::

IPv6-address-literal    =   "IPv6:" ip6-address
                        =~  IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)

Standardized-tag        =   Ldh-str
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]

dcontent        =   %d33-90 / %d94-126
                =~  [!-Z^-~]

General-address-literal =   Standardized-tag ":" 1*dcontent
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+

address-literal =   "[" ( IPv4-address-literal / IPv6-address-literal / General-address-literal ) "]"
                =~  \[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)]

Mailbox         =   Local-part "@" ( Domain / address-literal )
                =~  ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])

ユーザー入力の検証

一般的な使用例は、HTMLフォームなどでのユーザー入力の検証です。その場合、通常、アドレスリテラルを除外し、ホスト名に少なくとも2つのラベルを要求するのが妥当です。前のセクションから改善されたRFC 5321正規表現を基礎として使用すると、結果の式は次のようになります。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+

一部のホストで許可されているメールボックス名の種類("a..b"@example.netやなど"a b"@example.net)がわからないため、たとえば引用符で囲まれた文字列を除外するなど、ローカル部分をさらに制限することはお勧めしません。

また、リテラルトップレベルドメインのリストに対して明示的に検証したり、長さの制約を課したりすることもお勧めしません( ".museum"がどのように無効化されているかを思い出し[a-z]{2,4}てください)。

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?\.)*(net|org|com|info|等...)

明示的なトップレベルドメイン検証のパスをたどる場合は、正規表現を最新の状態に保つようにしてください。

その他の考慮事項

ドメイン部分(@記号の後)でホスト名のみを受け入れる場合、上記の正規表現は、必要に応じて最大63文字のラベルのみを受け入れます。ただし、ホスト名全体が最大253文字(ドットを含む)でなければならないという事実は強制されません。この制約は厳密に言えばまだ規則的ですが、このルールを組み込んだ正規表現を作成することは現実的ではありません。

特に入力の検証に正規表現を使用する場合のもう1つの考慮事項は、ユーザーへのフィードバックです。ユーザーが間違ったアドレスを入力した場合は、単純な「構文的に正しくないアドレス」よりも少し多くのフィードバックを提供するとよいでしょう。「バニラ」正規表現では、これは不可能です。

これら2つの考慮事項は、アドレスを解析することで対処できます。ホスト名の追加の長さの制約は、場合によっては、それをチェックする追加の正規表現を使用し、両方の式に対してアドレスを照合することによっても対処できます。

この回答の正規表現はどれも、パフォーマンスが最適化されていません。パフォーマンスに問題がある場合は、選択した正規表現を最適化できるかどうか(およびその方法)を確認する必要があります。


3
RFC 6532は5322を更新して、完全でクリーンなUTF-8を許可および含めるようにしています。詳細はこちら

ウィキペディアによると、ローカルパーツは、ドットで区切られている場合、1パーツあたり64文字の制限があるようです。また、RFC 5322は、ドットのローカルパーツがドメインの制限で解釈されることを示しています。たとえば、arbitrary-long-email-address-should-be-invalid-arbitrary-long-email-address-should-be-invalid.and-the-second-group-also-should-not-be-so-long-and-the-second-group-also-should-not-be-so-long@example.com検証しないでください。私はに(名前オプションドット前)と第2グループの(次のドットの後の名前)第1グループの「+」印を変更することをお勧め{1,64}
シャビモンテロ

コメントのサイズが制限されているため、ここで私が使用する予定の正規表現を示します。これは、この回答の冒頭にあるもので、ローカル部分のサイズを制限し、さらに「/」の前にバックスラッシュを追加しますPHPとregex101.comで必要な記号:PHPでは、次を使用します:$emailRegex = '/^([-!#-\'*+\/-9=?A-Z^-~]{1,64}(\.[-!#-\'*+\/-9=?A-Z^-~]{1,64})*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+$/';
Xavi Montero

注意:何らかの理由で、StackOverflowはレンダリングされたマークダウンからコピーするときに非表示の文字を追加します。それをregex101.comにコピーすると、そこに黒い点が表示されます。それらを削除して文字列を修正する必要があります...おそらく回答に統合されている場合、それらは正しくコピー可能です。ご不便おかけしてすみません。これは適切な回答なので、新しい回答は追加しません。また、コミュニティがこれを統合する必要があると考えない限り、直接編集したくありません。
Xavi Montero 2017年

@XaviMontero Xaviに貢献してくれてありがとう!ローカルパーツラベルの64文字の制限を記載したRFCへの参照はありますか?もしそうなら、私は喜んで答えを調整します。
リンケ

73

これについてはネット上にたくさんの例があります(RFCを完全に検証するものであると思いますが、メモリが機能する場合は数十行から数百行です)。人々はこの種のものを検証することに夢中になりがちです。@と少なくとも1つあることを確認しないでください。いくつかの単純な最小長を満たしています。偽のメールを入力しても、有効な正規表現に一致するのは簡単です。偽陽性は偽陰性よりも優れていると思います。


1
はい、でもどの RFCですか?:)この[RFC-5322–validator](stackoverflow.com/questions/201323/…)は、約40行しかありません。
tchrist 2010年

14
A 必須ではありません。TLDは電子メールアドレスを持つことができますが、IPv6アドレスが存在する可能性もあります
Sijmen Mulder

1
RFCは物語の終わりではありません:ICANNは「ドットレス
Synchro

64

許可される文字を決定するときは、アポストロフィを使用したハイフン付きの友達を覚えておいてください。私の会社が人事システムからの私の名前を使用して私の電子メールアドレスを生成するという事実を制御できません。これには、私の姓にアポストロフィが含まれています。私のメールアドレスが「無効」であるという理由で、ウェブサイトとのやり取りがブロックされた回数はわかりません。


4
これは、人の名前で何が許可され、何が許可されないかについて不当な仮定を行うプログラムで非常に一般的な問題です。そのような仮定をするべきではなく、関連するRFCが必要だと言っている文字を受け入れるだけです。
tchrist 2010

4
はい。プログラマーが電子メールアドレスの大文字を拒否することに特に腹を立てています。愚かなおよび/または怠惰。
PhiLho 2012年

63

この正規表現は、PerlのEmail :: Validライブラリからのものです。私はそれが最も正確であると信じています、それはすべての822に一致します。そして、それはO'Reillyの本の正規表現に基づいています:

正規表現の習得http://www.ora.com/catalog/regexp/)のJeffrey Friedlの例を使用して構築された正規表現 。

$RFC822PAT = <<'EOF';
[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\
xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf
f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\x
ff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015
"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\
xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80
-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*
)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\
\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\
x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n
\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([
^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\
\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\
x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()
]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\
x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04
0\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\
n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\
015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?!
[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\
x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\01
5()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]
)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^
()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\0
15()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][
^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\
n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\
x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?
:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-
\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*
(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015
()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()
]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\0
40)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\
[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\
xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*
)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80
-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x
80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t
]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\
\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])
*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x
80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80
-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015(
)]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\
\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t
]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\0
15()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015
()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(
\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|
\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80
-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()
]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\
\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x
80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015
()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\
\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^
(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-
\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\
n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|
\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))
[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff
\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\x
ff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(
?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\
000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\
xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\x
ff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)
*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\x
ff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-
\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)
*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\
]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]
)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-
\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\x
ff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(
?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80
-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<
>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:
\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]
*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)
*\)[\040\t]*)*)*>)
EOF

14
O_Oあなた​​はそれが何をしているのかを理解するために正規表現マスターである必要もあります
Chris McGrath

45

PHPで書いているときに、PHPのビルトイン検証を電子メールに使用することをお勧めします。

filter_var($value, FILTER_VALIDATE_EMAIL)

5.3.6より前のphp-versionを実行している場合は、この問題に注意してください:https : //bugs.php.net/bug.php?id=53091

この組み込み検証がどのように機能するかについて詳しく知りたい場合は、こちらを参照してください:PHPのfilter_var FILTER_VALIDATE_EMAILは実際に機能しますか?


正確に私が言うつもりでした。IDNを処理しませんが、事前にpunyコードに変換することでこれを解決します。PHP> = 5.3には、このためのidn_to_ascii()があります。電子メールを検証するための最良かつ最も簡単な方法の1つ。
テイラー、

43

Cal Henderson(Flickr)がPHPでParsing Email Adressesと呼ばれる記事を書き、適切なRFC(2)822準拠のEメールアドレス解析を行う方法を示しています。ccライセンスされているphp、python、ruby のソースコードを取得することもできます。


それa@bは有効だったと私に言った
dsdsdsdsd 14

1
@dsdsdsdsd a@b有効だから...この場合bはトップレベルドメインです。
rink.attendant.6 2015

42

私は自分の正規表現を使って作成することはありません。誰か他の人がすでにより良いバージョンを考えている可能性があるからです。私はいつもregexlibを使って自分の好みに合ったものを見つけています。


1
これは長さと内容のフラグが立てられましたが、41票の良い貢献であり、削除しないでください。
ウィル

37

本当に使えるものはありません。
私は私の中でいくつかの問題を議論する電子メールアドレスの検証のためであるとの回答があっPHPライブラリ?、それはまた、メールアドレスのRegexp認識で難しい議論されていますか?

要するに、単一の使用可能な正規表現が適切な仕事をすることを期待しないでください。そして、最高の正規表現は、電子メールの有効性ではなく、構文を検証します(jhohn@example.comは正しいですが、おそらくバウンスします...)。


私が間違っている場合は修正してください。ただし、PHPはPCREパターンを使用していると思います。その場合は、AbigailのRFC 5322パターンに似たものを作成できるはずです。
tchrist 2010年

@tchrist:PCREがこの構文に追いついたかどうかはわかりません(私が発見しました)。もしそうなら、PHPのPCREがこのバージョンのPCREに追いついたかどうかはわかりません...まあ、私がこの構文を正しく理解していれば、正規表現よりもはるかに明確で完全なPEGパーサーを使用することもできます。
PhiLho

PCRE それに追いついていますが、おそらくPHPはPCREに追いついていません。☹
tchrist

36

少なくとも有効な電子メールアドレスを拒否しない単純な正規表現の1つは、何かをチェックし、その後に@記号、次に何かの後にピリオドと少なくとも2つのものをチェックすることです。何も拒否しませんが、仕様を確認した後、有効で拒否されるメールを見つけることができません。

メール=〜 /.+@[^@]+\.[^@]{2,}$/


3
これは私が探していたものです。それほど制限的ではありませんが、@が1つだけであることを確認します(リストを解析していて、コンマの欠落がないことを確認したいため)。参考までに、引用符で囲まれている場合は左側に@を付けることができます:Valid_email_addresses、しかしそれはかなりフリンジです。
Josh、

2
それを使用した後、それが正確に機能しないことに気づきました。 /^[^@]+@[^@]+\.[^@]{2}[^@]*$/ 実際に1 @記号をチェックします。あなたの正規表現は、最後の。*のために複数を通過させます。
ジョシュ

1
正しい。無効なメールをすべて拒否しようとするのではなく、有効なメールアドレスを拒否しないようにします。
スパイ

1
これを使用する方がはるかに良いでしょう/^[^@]+@[^@]+\.[^@]{2,4}$/。@以外の2〜4文字で終わるようにしてください。@Joshが指摘したように、最後に追加の@が許可されます。ただし、これを次のように変更することもできます/^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/。すべてのトップレベルドメインがaZ文字であるため。あなたは置き換えることができ45、トップレベルドメイン名は、今後も長くなるようにできる以上。
2013年

@ FLY、ka @ foo。正しい結果を返します。それは、標準的にはそうですか?
SexyBeast 2015年

29

jQuery Validationプラグインで採用されているものを使用できます。

/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i

これは良い仕事をしているようです。これは許可されましa-b'c_d.e@f-g.hたが、a-b'c_d.@f-g.hand などの不適切なバリエーションをキャッチできましたa-b'c_d.e@f-.h
dsdsdsdsd 2014

25

電子メールアドレスを検証するための最適な正規表現の最も包括的な評価については、このリンクを参照してください。「正規表現を検証する電子メールアドレスの比較

参照用の現在のトップ式は次のとおりです。

/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i

spoon16:そのリンクは本当に正しくありません。電子メールアドレスを検証するための完全なパターンはあり得ないというその声明は、明らかに誤りです。することはできますが、RFCに従って文字を確認する必要があります。また、正しいRFCを選択する必要もあります。
tchrist 2010年

文字列を適切にエスケープして変換した後でも、現在の「最良の」はjava regexでは機能しません。
エリックチェン

23

ラテン語以外のドメイン名(中国語、アラビア語、ギリシャ語、ヘブライ語、キリル文字など)が近い将来に許可されることは言うまでもありません。使用するメールの正規表現は誰もが変更する必要があります。これらの文字はでカバーされてい[a-z]/iないため\wです。それらはすべて失敗します。

結局のところ、最高の電子メールアドレスを検証するための方法は、実際にはまだある送信アドレスを検証するために、問題のアドレスに電子メールを。メールアドレスがユーザー認証の一部である場合(登録/ログイン/など)、ユーザーアクティベーションシステムと完全に組み合わせることができます。つまり、固有のアクティベーションキーのリンクを含むメールを指定のメールアドレスに送信し、ユーザーがメール内のリンクを使用して新しく作成したアカウントをアクティベートした場合にのみログインを許可します。

正規表現の目的が、指定された電子メールアドレスが正しい形式になっていないことをUIでユーザーにすばやく通知することだけである場合でも、基本的に次の正規表現と一致するかどうかを確認することをお勧めします。

^([^.@]+)(\.[^.@]+)*@([^.@]+\.)+([^.@]+)$

そのような単純な。名前とドメインで使用されている文字をどうして気にするのですか?サーバーではなく、有効なメールアドレスを入力するのはクライアントの責任です。クライアントがのような構文的に有効なメールアドレスを入力した場合でもaa@bb.cc、これが正当なメールアドレスであることを保証するものではありません。正規表現でそれをカバーすることはできません。


4
通常、認証メッセージの送信はこの種のものにとって最善の方法であり、構文的に正しく有効なのは同じではありません。「確認」のためにメールアドレスを2回入力させられたとき、入力した内容を確認できないかのようにイライラします。とにかく1つ目を2つ目にコピーするだけで、どんどん使われているようです。
PeteT

同意する!しかし、この正規表現はspaces@.egの後で許可されるため、有効ではないと思います。test@test.ca com net上記の正規表現を使用して、有効な電子メールを検討します。
CB4 2017年

20

HTML5の仕様では、提案する電子メールアドレスを検証するための簡単な正規表現を:

/^[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 5322に準拠しいません。

注:この要件は、RFC 5322の意図的な違反です。RFC5322は、電子メールアドレスの構文が厳密すぎ(@文字の前)、あいまいすぎ(@文字の後ろ)、緩すぎる(コメント、空白文字が許可されている、そして、ほとんどのユーザーにとってなじみのない方法で文字列を引用しました)ここで実用的になります。

RFC 3696エラッタ1690に従って、全長は254文字に制限することもできます。


ベストアンサー!w3の推奨事項へのリンクは次のとおりです。w3.org / TR / html5 / forms.html#valid-e-mail-address この正規表現は多くのブラウザで採用されています。
ライアンテイラー

3
これは最高の答えではありません!このパターンは、完全に無効な次のアドレスに一致します:invalid@emailaddress。あなたがそれを使う前に私は注意と多くのテストを強く勧めます!
シェリダン

@シェリダン、HTML5仕様に問題があると思われる場合は、こちらで問題を提起できます:github.com/w3c/html/issues
Luna

これは、stackoverflow.com / a / 8829363に追加するものではなく、その編集またはコメントとしてIMHOの方が優れています。

example @ localhostは有効ですが、実際のアプリケーションではドメイン拡張を適用する必要があります。これを行うには、最後の*を+に変更するだけです(パターンのその部分を0+から1+に変更します) )
Mitch Satchwell、2018年

15

鮮やかなデモンストレーションの場合、次のモンスターはかなり良いですが、構文的に有効なすべての電子メールアドレスを正しく認識しません。ネストされたコメントを最大4レベルまで認識します。

これはパーサーの仕事ですが、アドレスが構文的に有効であっても、配信できない場合があります。時々、「ねえ、みんなよ、ee-usを見て!」というヒルビリーの方法に頼らなければならないことがあります。

// derivative of work with the following copyright and license:
// Copyright (c) 2004 Casey West.  All rights reserved.
// This module is free software; you can redistribute it and/or
// modify it under the same terms as Perl itself.

// see http://search.cpan.org/~cwest/Email-Address-1.80/

private static string gibberish = @"
(?-xism:(?:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<DQ>(?-xism:(?-xism:[
^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D])))+<DQ>(?-xism:(?-xi
sm:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xis
m:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\
s*)+|\s+)*))+)?(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?
-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<(?-xism:(?-xi
sm:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^(
)\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(
?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))
|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<
>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]
+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:
(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s
*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xi
sm:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*
<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D]
)))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-x
ism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+
)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:(
?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?
-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s
*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(
?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)
+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-x
ism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-xi
sm:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:
\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+
)*\s*\)\s*)+|\s+)*)))>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-
xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))|(?-xism:(?-x
ism:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*
(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D])
)|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()
<>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s
]+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism
:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\
s*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-x
ism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)
*<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D
])))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\
\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-
xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)
+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:
(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(
?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[
^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\
s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+
(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism
:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:
[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+
))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*
)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism
:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\(
(?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A
\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-
xism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-x
ism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism
:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))
+)*\s*\)\s*)+|\s+)*))))(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?
>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:
\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0
D]))|)+)*\s*\)\s*))+)*\s*\)\s*)*)"
  .Replace("<DQ>", "\"")
  .Replace("\t", "")
  .Replace(" ", "")
  .Replace("\r", "")
  .Replace("\n", "");

private static Regex mailbox =
  new Regex(gibberish, RegexOptions.ExplicitCapture); 

12

公式の標準RFC 2822によると、有効なメールの正規表現は

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

あなたがJavaでそれを使いたいなら、それは本当にとても簡単です

import java.util.regex.*;

class regexSample 
{
   public static void main(String args[]) 
   {
      //Input the string for validation
      String email = "xyz@hotmail.com";

      //Set the email pattern string
      Pattern p = Pattern.compile(" (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"
              +"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")"
                     + "@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]");

      //Match the given string with the pattern
      Matcher m = p.matcher(email);

      //check whether match is found 
      boolean matchFound = m.matches();

      if (matchFound)
        System.out.println("Valid Email Id.");
      else
        System.out.println("Invalid Email Id.");
   }
}

1
正規表現には、最初の大文字が含まれていません(例:Leonardo.davinci@gmail.com)。これは一部のユーザーにとって煩わしい場合があります。代わりにこれを使用してください:(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Kebab Krabby

@KebabKrabbyありがとう、答えを編集してください。変更を受け入れます。
AZ_

その変更を回答に追加すると、RFC 2822にはならないので、それが正しいかどうかはわかりません。
ケバブクラビー

11

ここに私が使っているPHPがあります。ここで別のコメンターによって宣言されているように、また応答時間を維持し、サーバーの負荷を軽減することに関して、「偽陽性は偽陰性よりも優れている」という精神でこのソリューションを選択しました...サーバーリソースを無駄にする必要はありませんこれが最も単純なユーザーエラーを取り除く正規表​​現。必要に応じて、いつでもテストメールを送信してこれを追跡できます。

function validateEmail($email) {
  return (bool) stripos($email,'@');
}

1
a)「無駄なサーバーリソース」はごくわずかですが、その傾向がある場合は、JSを使用してクライアント側で実行できます。b)登録メールを送信するために何が必要で、ユーザーはme @ forgotthedotcomと入力しますか?あなたの「解決策」は失敗し、ユーザーを失います。
johnjohn

a)JavaScriptが無効になっている場合に失敗するJS検証に依存することも、最良のアイデアのようには聞こえません(ほんのちょっと)
auco

11

RFC 5322標準:

ドットアトムのローカル部分、引用文字列のローカル部分、廃止(ドットアトムと引用文字列の混在)ローカル部分、ドメイン名ドメイン、(IPv4、IPv6、およびIPv4マップIPv6アドレス)ドメインリテラルドメインを許可します。および(ネストされた)CFWS。

'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD'

RFC 5321標準:

ドットアトムのローカル部分、引用文字列のローカル部分、ドメイン名ドメイン、および(IPv4、IPv6、およびIPv4にマップされたIPv6アドレス)ドメインリテラルドメインを許可します。

'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!"?(?>\\\[ -~]|[^"]){65,}"?@)(?>([!#-\'*+\/-9=?^-~-]+)(?>\.(?1))*|"(?>[ !#-\[\]-~]|\\\[ -~])*")@(?!.*[^.]{64,})(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?2)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?3)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?3)(?>:(?3)){0,6})?::(?4)?))|(?>(?>IPv6:(?>(?3)(?>:(?3)){5}:|(?!(?:.*[a-f0-9]:){6,})(?5)?::(?>((?3)(?>:(?3)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?6)){3}))\])$/iD'

基本:

ドットアトムのローカル部分とドメイン名ドメインを許可します(TLDが2〜6のアルファベット文字に制限された少なくとも2つのドメイン名ラベルが必要です)。

"/^(?!.{255,})(?!.{65,}@)([!#-'*+\/-9=?^-~-]+)(?>\.(?1))*@(?!.*[^.]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?\.){1,126}[a-z]{2,6}$/iD"

悪魔の言葉は何ですか?私は/Dフラグを見ました、そしてあなたはそれを一重引用符で引用しましたが、パターンを区切るためにスラッシュも使用しましたか?これはPerlではなく、PCREにすることはできません。それはPHPですか?これらは、のような再帰を許可する唯一の3つだと思い(?1)ます。
tchrist 2010年

それはPCREを使用するPHPにあります。スラッシュは、括弧、大括弧、およびもちろんスラッシュと単一引用符のような特殊文字を区切るためにのみ使用されます。/ Dフラグは、知らない場合は、文字列の末尾に改行が追加されないようにするためのものです。
MichaelRushton、2011

9

奇妙なことに、4文字のTLDを許可することはできません。あなたは.info.nameからの人々を禁止し、長さ制限は.travel.museumを停止しますが、そうです、それらは2文字のTLDと3文字のTLDより一般的ではありません。

大文字のアルファベットも許可する必要があります。メールシステムはローカル部分とドメイン部分を正規化します。

ドメイン部分の正規表現の場合、ドメイン名は「-」で開始したり、「-」で終了したりすることはできません。ダッシュはその間にとどまることができます。

PEARライブラリーを使用した場合は、そのメール機能を調べてください(正確な名前/ライブラリーを忘れた場合)。1つの関数を呼び出すことで電子メールアドレスを検証でき、RFC822の定義に従って電子メールアドレスを検証します。


2
@Joseph Yee:RFC 822は少し日付が遅れていませんか?
tchrist 2010年

8
public bool ValidateEmail(string sEmail)
{
    if (sEmail == null)
    {
        return false;
    }

    int nFirstAT = sEmail.IndexOf('@');
    int nLastAT = sEmail.LastIndexOf('@');

    if ((nFirstAT > 0) && (nLastAT == nFirstAT) && (nFirstAT < (sEmail.Length - 1)))
    {
        return (Regex.IsMatch(sEmail, @"^[a-z|0-9|A-Z]*([_][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*(([_][a-z|0-9|A-Z]+)*)?@[a-z][a-z|0-9|A-Z]*\.([a-z][a-z|0-9|A-Z]*(\.[a-z][a-z|0-9|A-Z]*)?)$"));
    }
    else
    {
        return false;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.