Normal bir ifade kullanarak bir e-posta adresini nasıl doğrulayabilirim?


3311

Yıllar içinde yavaş yavaş sunucu parçası olarak bir IP adresi kullanmadığı varsayılarak, MOST e-posta adreslerini doğru bir şekilde doğrulayan düzenli bir ifade .

Birkaç PHP programında kullanıyorum ve çoğu zaman çalışıyor. Bununla birlikte, zaman zaman siteyi kullanan bir site ile sorun yaşayan bir kişi ile iletişime geçiyorum ve bazı ayarlamalar yapmak zorunda kalıyorum (en son 4 karakterli TLD'lere izin vermediğimi fark ettim).

E-postaları doğrulamak için gördüğünüz veya gördüğünüz en iyi normal ifade nedir?

Birkaç kısa ifade kullanan işlevleri kullanan birçok çözüm gördüm, ancak daha karmaşık bir işlevde birkaç kısa ifade yerine basit bir işlevde uzun bir karmaşık ifadeye sahip olmayı tercih ederim.



5
Bir IDNA'nın doğru biçimlendirildiğini doğrulayabilen normal ifade stackexchange'e uymuyor. (kanonikleştirme kuralları gerçekten dolambaçlı ve özellikle normal ifade işlemine uygun değildi)
Jasen


Normal ifadeler , bazı durumlarda bir e-posta conunun boşluk içerebileceği ve diğer zamanlarda boşluk içeremeyeceği gibi değişken olabilir .
ểơửṩgǻňạcểơửṩ

Yanıtlar:


2439

Tam RFC 822 uyumlu regex verimsiz ve uzunluğu sebebi ile karanlık olduğunu. Neyse ki, RFC 822 iki kez yerini aldı ve e-posta adresleri için mevcut spesifikasyon RFC 5322'dir . RFC 5322, birkaç dakika çalışıldığında anlaşılabilir ve gerçek kullanım için yeterince verimli olan bir normalliğe yol açar.

Bir RFC 5322 uyumlu regex de sayfanın üst kısmında bulunabilir http://emailregex.com/ ancak izin veren bir hata ile internet etrafında yüzen IP adresi desenini kullanan 00bir de işaretsiz bayt ondalık değerlerden herhangi için yasadışı olan nokta ile ayrılmış adres. Geri kalanı RFC 5322 dilbilgisi ile tutarlı görünüyor ve grep -Poetki alanı adları, IP adresleri, kötü adresler ve tırnaklı ve tırnaksız hesap adları dahil olmak üzere çeşitli testler geçiriyor.

Düzeltme 00IP desende hata, bir çalışma ve oldukça hızlı regex elde ederiz. (Gerçek kod için oluşturulmuş sürümü işaretleme yerine kazıyın.)

(: [A-z0-9 # $% & '* + / = ^ _ `{|} ~ -? + (?.!: \ [A-z0-9 # $% &!]'? * + / ? = ^ _ `{|} ~ -] +) * |" (: [\ x01- \ X08 \ x0b \ x0c \ x0e- \ x1f \ x21 \ x23- \ X5b \ x5d- \ x7f] | \\ [\ x01- \ X09 \ x0b \ x0c \ x0e- \ x7f]) * ") '(: (: [a-0-9] (:? [a-z0-9 -] * [a-z0 -9]) \) + [a-0-9] (:.?? [a-z0-9 -] * [a-0-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]) +) \])

veya:

(?:[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])+)\])

İşte şeması arasında sonlu durum makinesi regexp'nin kendisinden daha açık yukarıda regexp'nin için resim açıklamasını buraya girin

Perl ve PCRE'deki (örneğin PHP'de kullanılan regex kütüphanesi) daha karmaşık desenler, RFC 5322'yi sorunsuz bir şekilde ayrıştırabilir . Python ve C # bunu yapabilir, ancak ilk ikisinden farklı bir sözdizimi kullanırlar. Ancak, daha az güçlü desen eşleştirme dillerinden birini kullanmak zorunda kalırsanız, gerçek bir ayrıştırıcı kullanmak en iyisidir.

RFC'ye göre onaylamanın, söz konusu adresin sağlanan alan adında gerçekten var olup olmadığı veya adresi giren kişinin gerçek sahibi olup olmadığı hakkında kesinlikle hiçbir şey söylemediğini anlamak da önemlidir. İnsanlar her zaman bu şekilde posta listelerine kaydolur. Daha ayrıntılı bir doğrulama gerektiren bu düzeltme, bu adrese, adresle aynı web sayfasına girilmesi gereken bir onay jetonu içeren bir ileti gönderilmesini içerir.

Onay jetonları, ona giren kişinin adresini aldığınızı bilmenin tek yoludur. Bu nedenle çoğu posta listesi kaydolmayı onaylamak için bu mekanizmayı kullanmaktadır. Sonuçta, herkes durdurabilir president@whitehouse.govve bu yasal olarak ayrıştırılır, ancak diğer ucunda kişi olması muhtemel değildir.

PHP için, gereken değil , belirtilen modeli kullanmak doğrula'da PHP ile bir E-Posta Adresi, Doğru hangi aynen aktarıyorum:

Yaygın kullanım ve yaygın özensiz kodlamanın, kayıtlı resmi standarttan daha kısıtlayıcı olan e-posta adresleri için fiili bir standart oluşturma tehlikesi vardır.

Bu, diğer RFC olmayan kalıplardan daha iyi değildir. Hatta işlemek için bile akıllı yeterli değildir RFC 822 , tek başına RFC 5322. izin Bu bir Ancak olduğunu.

Süslü ve bilgiç olmak istiyorsanız, eksiksiz bir devlet motoru uygulayın . Normal bir ifade yalnızca temel bir filtre görevi görebilir. Normal ifadelerle ilgili sorun, birisine mükemmel bir şekilde geçerli e-posta adreslerinin geçersiz (yanlış bir pozitif) olduğunu söylemesidir, çünkü normal ifadeniz bunu işleyemez, kullanıcının bakış açısından kaba ve kaba. Bu amaçla bir durum motoru, her RFC'ye göre e-posta adresini ayırdığı için geçersiz kabul edilecek e-posta adreslerini hem doğrulayabilir hem de düzeltebilir. Bu, potansiyel olarak daha hoş bir deneyim sağlar, örneğin

Belirtilen 'myemail @ address, com' e-posta adresi geçersiz. Şunu mu demek istediniz: 'myemail@address.com'?

Yorumlar da dahil olmak üzere E-posta Adreslerini Doğrulama konusuna bakın . Veya Normal İfadeleri Doğrulayan E-posta Adresini Karşılaştırma .

Düzenli ifade görselleştirme

Debuggex Demosu


179
"İyi bir düzenli ifade yok" dediniz. Bu genel veya e-posta adresi doğrulamasına özgü mü?
Tomalak

37
@Tomalak: sadece e-posta adresleri için. Bortzmeyer'in dediği gibi, RFC son derece karmaşıktır
Luk

37
Bahsettiğiniz linux dergi makalesi birçok açıdan yanlıştır. Özellikle Lovell, RFC3696'ya yönelik erratayı açıkça okumamıştır ve RFC'nin yayınlanan sürümündeki bazı hataları tekrarlar. Daha fazla burada: dominicsayers.com/isemail
Dominic Sayers

9
Jeff Atwood, tüm geçerli e-posta adreslerini doğrulamak için bu blog gönderisinde hoş bir ifade içeriyor
CMircea

5
Geçerli HTML5 spesifikasyonunun , orijinal RFC'lerden kasıtlı olarak daha kısıtlayıcı olan e-posta türü giriş doğrulaması için bir normal ifade ve ABNF içerdiğini unutmayın .
Senkro

746

E-posta adreslerini doğrulamak için normal ifadeler kullanmamalısınız.

Bunun yerine, MailAddress sınıfını şu şekilde kullanın:

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

MailAddressSınıf RFC822 tamamen uygun adresini doğrulamak için bir BNF ayrıştırıcı kullanır.

Kullanmayı planlıyorsanız MailAddressE-posta adresini doğrulamak için , bu yaklaşımın e-posta adresinin görünen adı bölümünü de kabul ettiğini ve tam olarak elde etmek istediğiniz şeyin bu olmayabileceğini unutmayın. Örneğin, bu dizeleri geçerli e-posta adresleri olarak kabul eder:

  • "user1@hotmail.com; user2@gmail.com"
  • "user1@hotmail.com; user2@gmail.com; user3@company.com"
  • "Kullanıcı Görünen Adı user3@company.com"
  • "user4 @ company.com"

Bazı durumlarda, dizelerin yalnızca son kısmı adres olarak ayrıştırılır; bundan önce kalanlar görünen addır. Görünen ad içermeyen düz bir e-posta adresi almak için normalleştirilmiş adresi orijinal dizenize göre kontrol edebilirsiniz.

bool isValid = false;

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

Ayrıca, sonunda nokta gibi bir adres user@company.MailAddress tarafından da kabul edilir.

Gerçekten normal ifade kullanmak istiyorsanız, işte burada :

(?: (?: \ 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'daki MailAddress sınıfının e-posta adreslerini doğrulamada önceki sürümlere göre çok daha iyi olduğunu göreceksiniz. Bazı önemli iyileştirmeler yaptım.
Jeff Tucker

7
Bence bu daha basit kimlikler için ... işe yaramaz ... a @ b doğrulamaz. ar@b.com yalnızca ar @ b olana kadar eşleşir, .com eşleşmez. Ancak, "Ben benim" gibi bir şey @ [10.10.10.10] işe yarıyor! :)
Raze

5
Bu RFC uyumlu normal ifade doğrulayıcılarının, kabul etmek istemeyeceğiniz birçok e-posta adresine "a <body / onload = alert (' lol.com?'+document.cookies ) @aa> "Bu, perl'in
Matthew Lock

9
@MatthewLock: Bu bundan daha kötü değil fake@not-a-real-domain.name. Sen olmamalıdır XSS önlemek için e-posta doğrulama güveniyor.
SLaks

10
@MatthewLock: Hayır. SQL sorgularından kaçmanız gerekir (veya daha iyisi parametreleri kullanın). Sterilizasyon uygun bir savunma değildir.
SLaks

536

Bu soru çok soruluyor, ancak sanırım geri çekilip kendinize neden e-posta adreslerini sözdizimsel olarak doğrulamak istediğinizi sormalısınız ? Gerçekten faydası nedir?

  • Ortak yazım hatalarını yakalamaz.
  • İnsanların geçersiz veya oluşturulmuş e-posta adresleri girmesini veya başka birinin adresini girmesini engellemez.

Bir e-postanın doğru olduğunu doğrulamak istiyorsanız, bir onay e-postası göndermekten başka bir seçeneğiniz yoktur ve kullanıcının buna cevap vermesini sağlayabilirsiniz. Birçok durumda olacak olması güvenlik nedenleriyle veya etik nedenlerden dolayı zaten bir onay posta göndermek için (böylece olabildiğince kendi rızaları bir hizmete kadar değil mesela işareti birisi).


92
Sadece basit hataları yakalamak için bir müşteri tarafı doğrulamasında alana bir şey girdiğini kontrol etmeye değer olabilir - ama genel olarak haklısınız.
Martin Beckett

8
Martin, sana bir +1 verdim, ancak daha sonra foobar @ dk'nın geçerli bir e-posta olduğunu okumak için. Güzel olmaz, ancak hem RFC uyumlu hem de sağduyu kullanmak istiyorsanız, bu gibi durumları tespit etmeli ve kullanıcıdan doğru olduğunu onaylamasını istemelisiniz.
philfreo

106
@olavk: Birisi yazım hatası yaparsa (örneğin:) me@hotmail, açık bir şekilde onay e-postanızı almayacaklar ve sonra neredeler ? Artık sitenizde değiller ve neden kayıt olamadıklarını merak ediyorlar. Aslında hayır değiller - seni tamamen unutmuşlar. Ancak, hala sizin yanınızdayken normal bir regex ile temel bir akıl sağlığı kontrolü yapabilirseniz, o hatayı hemen yakalayabilir ve mutlu bir kullanıcınız var.
nickf

5
@ JacquesB: Mükemmel bir noktaya değindin. Sadece RFC başına toplayıcı geçmesi, kullanıcının adresi olduğu anlamına gelmez. Aksi takdirde tüm bu president@whitehouse.govadresler çok netbusili bir baş komutanı gösterir. :)
tchrist

39
Siyah ya da beyaz olması gerekmez. E-posta yanlış görünüyorsa kullanıcıya bunu bildirin. Kullanıcı hala devam etmek istiyorsa, bırakın. Kullanıcıyı normal ifadenize uymaya zorlamayın, bunun yerine kullanıcının bir hata olabileceğini bilmesine yardımcı olmak için normal ifadeyi bir araç olarak kullanın.
ninjaneer

354

Her şey ne kadar doğru olmak istediğinize bağlıdır. Benim amacım için, sadece bob @ aol.com(e-postalardaki boşluklar) veya steve(hiç alan yok) veya mary@aolcom(.com'dan önce bir dönem yok ) gibi şeyleri dışarıda tutmaya çalışıyorum.

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

Elbette, geçerli e-posta adresleri olmayan şeylerle eşleşecektir, ancak bu yaygın basit hatalar alma meselesidir.

Bu normal ifade üzerinde yapılabilecek çok sayıda değişiklik var (ve bazıları bu cevap için yorumlarda yer alıyor), ancak basit ve anlaşılması kolay ve iyi bir ilk girişim.


6
Geçerli ve çalışan bir e-posta adresi olan foobar @ dk ile eşleşmiyor (muhtemelen çoğu posta sunucusu kabul etmeyecek veya bir şeyler ekleyecektir.)
bortzmeyer

3
Evet, olacak. Kendin denemenizi öneririm. $ perl -le'print q{foo@bar.co.uk} = ~ /^\S+@\S+\.\S+$/? q {Y}: q {N} '
Andy Lester

7
@Richard: .dahil edilmiştir \S.
David Thornley

43
JJJ: Evet, bir sürü saçmalıkla eşleşecek. & $ * # $ (@ $ 0 (%)) $ #.) & *) (* $ mary@aolcomDa. YMMV.
Andy Lester

5
Sadece @işaretleri kontrol etmek için : /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/ jsfiddle.net/b9chris/mXB96
Chris

338

En iyi ne demek istediğinize bağlıdır: Her geçerli e-posta adresini yakalamaktan bahsediyorsanız aşağıdakileri kullanın:

(?:(?:\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 ) Daha basit bir şey arıyorsanız, ancak bu en geçerli e-posta adreslerini yakalarsa aşağıdakileri deneyin:

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

EDIT: bağlantıdan:

Bu normal ifade yalnızca herhangi bir yorumu çıkarılmış ve boşlukla değiştirilmiş adresleri doğrular (bu modül tarafından yapılır).


10
Tüm adreslerle eşleşmiyor, önce bazılarının dönüştürülmesi gerekiyor. Bağlantıdan: "Bu normal ifade yalnızca herhangi bir yorumu kaldırılmış ve boşlukla değiştirilmiş adresleri doğrular (bu modül tarafından yapılır)."
Chas. Owens

47
Bana email addressikincisinden yanlış geçen, ancak daha uzun regex tarafından yakalananlardan bir örnek verebilir misiniz ?
Lazer

4
Bir zamanlar sevmiş olmama rağmen, bu bir RFC 5322 değil, bir RFC 822 doğrulayıcısı .
tchrist

24
@Lazer in..valid @ example.com basit bir örnek olacaktır. Yerel bölümde art arda iki tırnaksız noktaya izin verilmiyor.
Randal Schwartz

5
@Mikhail perl ama aslında kullanmamalısınız.
İyi Kişi

287

[GÜNCELLENDİ] E-posta adresi doğrulaması hakkında bildiğim her şeyi burada derledim : http://isemail.info . Buradaki yorumların çoğuna katılıyorum, validasyonun cevabın sadece bir parçası olduğunu; makalemi http://isemail.info/about adresinde görebilirsiniz .

is_email (), bildiğim kadarıyla, belirli bir dizenin geçerli bir e-posta adresi olup olmadığını kesin olarak söyleyecek tek doğrulayıcıdır. Http://isemail.info/ adresinden yeni bir sürüm yükledim

Cal Henderson, Dave Child, Phil Haack, Doug Lovell, RFC5322 ve RFC 3696'dan test senaryolarını derledim. Toplamda 275 test adresi. Tüm bu testleri bulabildiğim tüm ücretsiz doğrulayıcılarla karşılaştırdım.

Kullanıcılar doğrulayıcılarını geliştirdikçe bu sayfayı güncel tutmaya çalışacağım. Cal, Michael, Dave, Paul ve Phil'e, bu testleri derlerken ve kendi doğrulamamın yapıcı eleştirilerinde yardımları ve işbirlikleri için teşekkürler .

İnsanlar özellikle RFC 3696'ya karşı olan hatalardan haberdar olmalıdır . Kanonik örneklerden üçü aslında geçersiz adreslerdir. Ve bir adresin maksimum uzunluğu 320 değil , 254 veya 256 karakterdir .


Bu doğrulayıcı da doğru görünüyor. [... zaman geçiyor ...] Hm, 3693 veya errata değil, sadece RFC 5322 gibi görünüyor.
tchrist

1
Çok hoş. Burada sadece güzel bir deneme almakla kalmıyor, aynı zamanda bir doğrulama test cihazı ve indirmek için bir kütüphane alıyoruz. Güzel cevap!
bgmCoder

Doğrulayıcınız punycode'u desteklemiyor (RFC 3492). name@öäü.at geçerli bir adres olabilir. (name@xn--4ca9at.at anlamına gelir)
Josef,

Merhaba @Josef. Sen doğrulamak için çalışmalısınız name@xn--4ca9at.atbu kod doğrulama, değil yorumlanması hakkında olduğu. Eğer bir punycode çevirmeni eklemek isterseniz, github.com/dominicsayers/isemail
Dominic Sayers

266

Başına W3C HTML5 spec :

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

Bağlam:

Bir geçerli bir e-posta adresi ABNF üretimini [...] eşleşen bir dizedir.

Not: Bu gereklilik, bir olan kasıtlı ihlali ait RFC 5322 ( “@” karakterinden sonra), çok belirsiz ( “@” karakteri öncesi) aynı anda çok katı olduğunu, e-posta adresleri için bir söz dizimi tanımlar, ve fazla gevşek ( çoğu kullanıcının bilmediği yorumların, boşluk karakterlerinin ve alıntılanan dizelerin burada) pratik kullanımlarına olanak tanır.

Aşağıdaki JavaScript ve Perl uyumlu düzenli ifade, yukarıdaki tanımın bir uygulamasıdır.

/^[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
Bu ilginç. Bu bir RFC ihlali, ama kasıtlı bir ses ve sesne yapıyor. Gerçek dünya örneği: gmail @ 'den önceki kısımdaki noktaları yok sayar, bu nedenle e-postanız test@gmail.com ise test etmek için e-posta gönderebilirsiniz. @ Gmail.com veya test .... @ gmail.com, bu adreslerin ikisi de RFC'ye göre geçersiz, ancak gerçek dünyada geçerlidir.
valentinas

Bence son bölüm '*' yerine '+' olmalı: ^ [a-zA-Z0-9.! # $% & '* + / =? ^ _ `{|} ~ -] + @ [a- zA-Z0-9 -] + (?: \. [a-zA-Z0-9 -] +) + $
mmmmmm

7
@mmmmmm john.doe@localhostgeçerlidir. Herhalde, gerçek bir dünya uygulamasında (yani bir toplulukta), * ile +
rabudde

3
@valentinas Aslında RFC yok değil bu yerel parçaları engellemez, ancak alıntı gerekmektedir. "test...."@gmail.comRFC'ye göre mükemmel şekilde geçerlidir ve anlamsal olarak eşdeğerdir test....@gmail.com.
Rinke

. @ Veya .. @ ile bir adrese göndermeye çalışırsam şirketimin geçişi üzerinden python kullanarak e-posta göndermeye çalışırken hata alıyorum. Aslında _ _ için de durum böyle. Bunu göndermeden önce alıcının yapacağına güvenmektense kaldırmayı tercih ederim.
ndvo

201

Perl 5.10 veya daha yeni sürümlerde kolaydır:

/(?(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
Bunu Python'da görmek isterdim
TDC

4
Sadece addrspecparçanın bir alt kümesinin soru ile gerçekten ilgili olduğunu düşünüyorum . Daha fazlasını kabul etmek ve sistemin tam RFC5822 adreslerini kabul etmeye hazır olmayan başka bir kısmı olsa da iletmek, kendi ayağınız gibidir.
dolmen

3
Harika (+1) ama teknik olarak elbette bir regex değil ... (dilbilgisi düzenli olmadığından imkansız olurdu).
Rinke

10
regexes bir süre önce düzenli olmayı bıraktı. Yine de geçerli bir Perl 'regex'!
rjh

4
IDEone üzerinde bu normal ifade için bir test oluşturdum: ideone.com/2XFecH Ancak, "mükemmel" olarak adil değil. Kim girecek isterdi? Bir şey mi kaçırıyorum?
Mike

159

kullanırım

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

Hangi ASP.NET'te RegularExpressionValidator tarafından kullanılır.


28
Boo! Adresinin (kötü tavsiye edilen) adresi !@mydomain.netreddedildi.
Phrogz

3
Bu sayfaya göre data.iana.org/TLD/tlds-alpha-by-domain.txt en üst düzeyde tek bir karaktere sahip alan yok, örneğin "birşeyler.c", "bir şey.a ", burada sürüm en az 2 karakteri destekleyin: "something.pl", "something.us":^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
Tomasz Szulc

4
@Wayne Whitty. E-posta doğrulamasını test etmek dışında, adreslerin büyük çoğunluğuna mı yoksa hiç kimsenin kullanamayacağı adresler de dahil olmak üzere TÜMÜ'ne hitap edip etmeyeceği konusuna öncelik verdiniz.
Patanjali

Cevabınızdaki @TomaszSzulc ekstra ters eğik çizgi kafa karıştırıcı, sadece düzelttim ve 2 karakter alan adı adı desteği çalışıyor, ^ \ w + ([- +. '] \ W +) * @ \ w + ([-.] \ W +) * \. \ w {2,} ([-.] \ w +) * $
Aqib Mumtaz

2
bu başarısız simon-@hotmail.comolan aslında geçerli (bir müşterimiz benzer bir adrese sahipti) ``
Simon_Weaver

142

En iyisini bilmiyorum, ancak adreslerin yorumları çıkarılmış ve boşlukla değiştirildiği sürece bu en azından doğrudur.

Ciddi anlamda. E-postaları doğrulamak için önceden yazılmış bir kütüphane kullanmalısınız. En iyi yol muhtemelen bu adrese bir doğrulama e-postası göndermektir.


2
Bildiğim kadarıyla bazı kütüphaneler de yanlış. Belli ki PHP PEAR'ın böyle bir hatası olduğunu hatırlıyorum.
bortzmeyer

Bu sayfanın alt kısmında spesifikasyondan birkaç şey hakkında bir feragatname var. normal ifade desteklemiyor.
Chris Vest

7
Bu bir RFC 822 spesifikasyonu, RFC 5322 spesifikasyonu değil.
tchrist

12
Sonuçta, bir e-posta adresini gerçekten doğrulamanın tek yolunun bir e-posta göndermesi ve bir cevap beklemesidir.
Blazemonger

109

Doğrulamak istediğim e-posta adresleri, bir ASP.NET web uygulaması tarafından System.Net.Mail ad alanını kullanarak bir kişi listesine e-posta göndermek için kullanılacak. Yani, bazı çok karmaşık düzenli ifadeler kullanmak yerine, adresten bir MailAddress örneği oluşturmaya çalışıyorum. Adres düzgün oluşturulmamışsa, MailAddress yorumlayıcısı bir istisna atar. Bu şekilde, en azından e-postayı kapıdan çıkarabileceğimi biliyorum. Tabii ki bu sunucu tarafı doğrulamadır, ancak en azından buna yine de ihtiyacınız vardır.

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
İyi bir nokta. Bu sunucu doğrulaması bazı geçerli adresleri reddetse bile, sorun değil, çünkü yine de bu sunucu teknolojisini kullanarak bu adrese gönderemeyeceksiniz. Veya, aynı araçları varsayılan araçlar yerine kullandığınız üçüncü taraf e-posta kitaplığını kullanarak da deneyebilirsiniz.
Kullanıcı

Bu .Net çerçeve kodunu nasıl kullandığını gerçekten seviyorum - tekerleği yeniden icat etmenin bir anlamı yok. Bu mükemmel. Basit, temiz ve e-postayı gerçekten gönderebilmenizi sağlar. Harika iş.
Cory House

... evet ve nasıl doğruladığına ilgi duyanlar için Reflector'daki koda bir göz atıyorlar - biraz var - ve bu normal bir ifade değil!
Tom Carter

2
Sadece bir not: MailAddress sınıfı RFC5322 ile eşleşmez, yalnızca doğrulama için kullanmak istiyorsanız (ve aynı zamanda göndermiyorsanız, bu durumda yukarıda belirtildiği gibi bir tartışma noktasıdır). Bakınız: stackoverflow.com/questions/6023589/…
porges

Sadece küçük bir sorun: sunucu tarafı doğrulayıcı kodunuzu daha fazla yeniden kullanılabilir yapmak istiyorsanız (bu durumda veya genel olarak), args.Valuealanı txtEmail.Textsabit kodlu gibi referanslamak yerine kullanmanızı öneririm . Sonuncusu, tek bir e-posta alanınız olduğu ancak başka şekilde önerilmediği sürece doğrulayıcınızı tek kontrol örneğine bağlayacaktır.
pholpar

109

Hızlı cevap

Giriş doğrulaması için aşağıdaki normal ifadeyi kullanın:

([-!#-'*+/-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])?)+

Bu normal ifadeyle eşleşen adresler:

  • RFC 5321/5322 ile tam uyumlu yerel bir bölüm (yani @ işaretinden önceki bölüm) olması,
  • her biri en fazla 63 karakter uzunluğunda en az iki etikete sahip bir ana bilgisayar adı olan bir alan adına (yani @ işaretinden sonraki bölüm) sahip olabilir.

İkinci kısıtlama, RFC 5321/5322 ile ilgili bir kısıtlamadır.

Ayrıntılı cevap

E-posta adreslerini tanıyan normal bir ifade kullanmak çeşitli durumlarda yararlı olabilir: örneğin bir belgedeki e-posta adreslerini taramak, kullanıcı girişini doğrulamak veya bir veri havuzunda bir bütünlük kısıtlaması olarak.

Ancak, adresin gerçekten var olan bir posta kutusuna atıfta bulunup bulunmadığını öğrenmek istiyorsanız, adrese mesaj göndermenin yerini tutamayacağına dikkat edilmelidir. Yalnızca bir adresin dilbilgisel olarak doğru olup olmadığını kontrol etmek istiyorsanız, normal bir ifade kullanabilirsiniz, ancak ""@[]kesinlikle mevcut bir posta kutusuna gönderme yapmayan, dilbilgisi açısından doğru bir e-posta adresi olduğunu unutmayın .

E-posta adreslerinin sözdizimi, özellikle RFC 822 ve RFC 5322 olmak üzere çeşitli RFC'lerde tanımlanmıştır . RFC 822 "orijinal" standart ve RFC 5322 en son standart olarak görülmelidir. RFC 822'de tanımlanan sözdizimi en yumuşak ve sonraki standartlar sözdizimini daha da sınırlandırmıştır, burada daha yeni sistemler veya hizmetler eski sözdizimini tanımalı, ancak asla üretmemelidir.

Bu cevap ben anlamında “e-posta adresini” alacağım addr-specRFC'lerde tanımlandığı (yani olarak jdoe@example.orgdeğil "John Doe"<jdoe@example.org>, ne some-group:jdoe@example.org,mrx@exampel.org;).

RFC sözdizimlerini normal ifadelere çevirmeyle ilgili bir sorun var: sözdizimleri düzenli değil! Bunun nedeni, e-posta adreslerinde sonsuz şekilde iç içe yerleştirilebilen isteğe bağlı yorumlara izin verirken, sonsuz iç içe yerleştirme normal bir ifade ile açıklanamaz. Yorum içeren adresleri taramak veya doğrulamak için bir ayrıştırıcıya veya daha güçlü ifadelere ihtiyacınız vardır. (Perl gibi dillerin bağlamsız gramerleri normal ifadeye benzer bir şekilde tanımlayacak yapılara sahip olduğunu unutmayın.) Bu cevapta yorumları göz ardı edeceğim ve yalnızca uygun düzenli ifadeleri dikkate alacağım.

RFC'ler, e-posta iletilerinin sözdizimlerini tanımlar, e-posta adresleri için değil. Adresler çeşitli başlık alanlarında görünebilir ve bunlar esas olarak tanımlandıkları yerdir. Üstbilgi alanlarında göründükleri zaman, adresler (sözcüksel belirteçler arasında) boşluk, yorum ve hatta satır aralığı içerebilir. Anlamsal olarak bunun bir önemi yoktur. Bu boşluğu, vb. Bir adresten kaldırarak anlamsal olarak eşdeğer kanonik bir temsil elde edersiniz . Bu nedenle, kanonik temsili first. last (comment) @ [3.5.7.9]olup first.last@[3.5.7.9].

Farklı amaçlar için farklı sözdizimleri kullanılmalıdır. (Muhtemelen çok eski) bir belgedeki e-posta adreslerini taramak istiyorsanız, sözdizimini RFC 822'de tanımlandığı şekilde kullanmak iyi bir fikir olabilir. Diğer yandan, kullanıcı girişini doğrulamak istiyorsanız, RFC 5322'de tanımlanan sözdizimi, muhtemelen sadece kanonik gösterimleri kabul eder. Özel durumunuz için hangi sözdiziminin geçerli olduğuna karar vermelisiniz.

Bu cevapta ASCII uyumlu bir karakter seti varsayarak POSIX "genişletilmiş" düzenli ifadeler kullanıyorum.

RFC 822

Aşağıdaki düzenli ifadeye ulaştım. Herkesi denemeye ve kırmaya davet ediyorum. Herhangi bir yanlış pozitif veya yanlış negatif bulursanız, lütfen bir yorumda gönderin ve ifadeyi mümkün olan en kısa sürede düzeltmeye çalışacağım.

([^][()<>@,;:\\". \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)*]))*

Ben de dahil olmak üzere RFC 822 ile tamamen uyumlu olduğuna inanıyorum errata . E-posta adreslerini yalnızca standart formlarında tanır. Boşluğu tanıyan (katlanan) bir normal ifade için aşağıdaki türevi inceleyin.

Türev, ifadeye nasıl geldiğimi gösterir. RFC'deki tüm ilgili dilbilgisi kurallarını tam olarak göründükleri gibi listeliyorum, ardından karşılık gelen normal ifade. Bir erratum yayınlandığında, düzeltilmiş dilbilgisi kuralı ("erratum" olarak işaretlenmiş) için ayrı bir ifade veriyorum ve güncellenmiş sürümü sonraki düzenli ifadelerde alt ifade olarak kullanıyorum.

3.1.4. Paragrafta belirtildiği gibi. Sözcük belirteçleri arasına RFC 822'nin isteğe bağlı doğrusal beyaz boşluğu eklenebilir. Uygulanabilir olduğunda ifadeleri bu kurala uyacak şekilde genişlettim ve sonucu "opt-lwsp" ile işaretledim.

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

Aşağıdaki düzenli ifadeye ulaştım. Herkesi denemeye ve kırmaya davet ediyorum. Herhangi bir yanlış pozitif veya yanlış negatif bulursanız, lütfen bir yorumda gönderin ve ifadeyi mümkün olan en kısa sürede düzeltmeye çalışacağım.

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

Ben errata dahil RFC 5322 ile tam uyumlu olduğuna inanıyorum . E-posta adreslerini yalnızca standart formlarında tanır. Boşluğu tanıyan (katlanan) bir normal ifade için aşağıdaki türevi inceleyin.

Türev, ifadeye nasıl geldiğimi gösterir. RFC'deki tüm ilgili dilbilgisi kurallarını tam olarak göründükleri gibi listeliyorum, ardından karşılık gelen normal ifade. Anlamsal olarak alakasız (katlanır) boşluk içeren kurallar için, "(normalleştirilmiş)" olarak işaretlenmiş ve bu boşlukları kabul etmeyen ayrı bir normal ifade veriyorum.

RFC'nin tüm "obs-" kurallarını görmezden geldim. Bu, normal ifadelerin yalnızca kesinlikle RFC 5322 uyumlu e-posta adresleriyle eşleştiği anlamına gelir. "Eski" adreslerle eşleşmeniz gerekiyorsa ("obs-" kurallarını içeren daha gevşek dilbilgisi gibi), önceki paragraftan RFC 822 normal ifadelerinden birini kullanabilirsiniz.

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^-~]*])

Bazı kaynakların (özellikle w3c ), RFC 5322'nin yerel kısımda (yani @ işaretinden önceki kısım) çok katı olduğunu iddia ettiğini unutmayın. Çünkü "..", "a..b" ve "a." olan değil , posta kutusu isim olarak kullanılabilir iken, geçerli bir nokta-atomu içerir. RFC Ancak gelmez onlar alıntı edilecek olması hariç, bu gibi yerel parçalar için izin verir. Yani yerinea..b@example.net"a..b"@example.net anlamsal olarak eşdeğer olan yazmalısınız .

Diğer kısıtlamalar

SMTP ( RFC 5321'de tanımlandığı gibi ), geçerli e-posta adresleri (veya aslında: posta kutusu adları) kümesini daha da kısıtlar. Eşleşen e-posta adresinin aslında bir e-posta göndermek için kullanılabilmesi için bu daha katı dilbilgisini uygulamak makul görünmektedir.

RFC 5321 temel olarak "yerel" kısmı (yani @ işaretinden önceki kısım) yalnız bırakır, ancak alan kısmı üzerinde daha sıkıdır (yani @ işaretinden sonraki kısım). Yalnızca nokta atomları yerine ana bilgisayar adlarına ve etki alanı değişmezleri yerine adres değişmezlerine izin verir.

RFC 5321'de sunulan dilbilgisi, hem ana bilgisayar adları hem de IP adresleri söz konusu olduğunda çok yumuşaktır. Bu taslağı ve RFC 1034'ü kılavuz olarak kullanarak söz konusu kuralları "düzeltme" özgürlüğünü aldım . İşte ortaya çıkan normal ifade.

([-!#-'*+/-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^-~]+)])

Kullanım durumuna bağlı olarak, normal ifadenizde "Genel adres değişmezine" izin vermek istemeyebileceğinizi unutmayın. Ayrıca (?!IPv6:), "Genel adres değişmezi" kısmının hatalı biçimlendirilmiş IPv6 adresleriyle eşleşmesini önlemek için son normal ifadede negatif bir ileriye baktığımı da unutmayın . Bazı normal ifade işlemcileri negatif ileriye bakmayı desteklemez. |(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+Tüm "Genel adres değişmezi" parçasını çıkarmak istiyorsanız alt dizeyi normal ifadeden çıkarın.

İşte türetme:

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^-~]+)])

Kullanıcı girişi doğrulaması

Yaygın bir kullanım durumu, örneğin bir html formunda kullanıcı giriş doğrulamasıdır. Bu durumda, adres değişmezlerini engellemek ve ana makine adında en az iki etiket gerektirmek genellikle mantıklıdır. Geliştirilmiş RFC 5321 normal ifadesini bir önceki bölümden temel alarak, elde edilen ifade şöyle olacaktır:

([-!#-'*+/-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])?)+

Bazı bölümlerin (gibi "a..b"@example.netveya hatta "a b"@example.net) izin verdiği posta kutusu adları ne tür bilmiyorum, çünkü yerel bölümü daha fazla, örneğin alıntı dizeleri önleyerek kısıtlama önermiyoruz .

Ayrıca, kelimenin tam anlamıyla üst düzey alan adlarının bir listesine karşı açıkça doğrulamayı veya hatta uzunluk kısıtlamalarını dayatmayı önermiyorum (".museum" nasıl geçersiz kılındığını unutmayın [a-z]{2,4}), ancak yapmanız gerekiyorsa:

([-!#-'*+/-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|vb...)

Açık üst düzey alan doğrulaması yolunda ilerlemeye karar verirseniz normal ifadenizi güncel tuttuğunuzdan emin olun.

Dikkat edilecek diğer noktalar

Yalnızca alan adı bölümündeki (@ işaretinden sonra) ana bilgisayar adlarını kabul ederken, yukarıdaki normal ifadeler olması gerektiği gibi yalnızca en fazla 63 karakter içeren etiketleri kabul eder. Ancak, tüm ana bilgisayar adının en fazla 253 karakter uzunluğunda olması gerektiğini (noktalar dahil) zorlamazlar. Her ne kadar bu kısıtlama hala düzenli olsa da, bu kuralı içeren bir regex yapmak mümkün değildir.

Özellikle girdi doğrulaması için normal ifadeler kullanıldığında göz önünde bulundurulması gereken bir başka nokta da kullanıcıya geri bildirimdir. Bir kullanıcı yanlış bir adres girerse, basit bir "sözdizimsel olarak yanlış adres" ten biraz daha fazla geri bildirim vermek iyi olur. "Vanilya" regexes ile bu mümkün değildir.

Bu iki husus adres ayrıştırılarak giderilebilir. Ana bilgisayar adlarındaki ek uzunluk kısıtlaması, bazı durumlarda, denetleyen ek bir normal ifade kullanılarak ve adresi her iki ifadeyle eşleştirilerek de giderilebilir.

Bu yanıttaki hiçbir normal ifade performans için optimize edilmemiştir. Performans bir sorunsa, seçtiğiniz normal ifadenin optimize edilip edilemeyeceğini (ve nasıl) optimize edeceğinizi görmelisiniz.


3
RFC 6532 güncelleştirmeleri 5322 izin ve tam, temiz UTF-8 içerecek şekilde. Ek ayrıntılar burada .

Wikipedia'ya göre, yerel parçanın, noktalı olduğunda, parça başına 64 karakter sınırlaması olduğu ve ayrıca RFC 5322, alanların kısıtlamaları ile yorumlanacak noktalı yerel parçayı ifade eder. Örneğin 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.comdoğrulamamalıdır. İlk gruptaki (+ isteğe bağlı noktadan önceki ad) ve ikinci gruptaki (sonraki noktalardan sonraki ad) "+" işaretlerini{1,64}
Xavi Montero olarak değiştirebilirsiniz

Yorumların boyutu sınırlı olduğundan, bu planın başlangıcında olan, kullanmayı planladığım normal ifade, artı yerel kısımdaki boyutu sınırlama ve "/" karakterinden önce ters eğik çizgi ekleme PHP ve ayrıca regex101.com gerekli sembolü: PHP kullanıyorum:$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

DİKKAT: Herhangi bir nedenle, StackOverflow, oluşturulan işaretlemeden kopyalarken gizli karakterler ekler. Regex101.com içine kopyalayın ve orada siyah noktalar göreceksiniz. Onları kaldırmak ve dize düzeltmek zorunda ... Belki cevap entegre, orada doğru kopyalanabilir vardır. Rahatsızlıktan dolayı özür dileriz. Bu doğru olanı olduğu için yeni bir cevap eklemek istemiyorum. Ayrıca, topluluk bunun içine entegre edilmesi gerektiğini düşünmedikçe doğrudan düzenlemek istemiyorum.
Xavi Montero

@XaviMontero Xavi'ye katkıda bulunduğu için teşekkürler! Yerel parça etiketlerinde 64 karakter sınırını belirten RFC'ye bir referansınız var mı? Eğer öyleyse, cevabı memnuniyetle ayarlayabilirim.
Rinke

73

Net bunun bol örnekleri vardır (ve bence tam olarak RFC doğrulayan biri - ama bellek hizmet eğer onlarca / yüzlerce satır uzun). İnsanlar bu tür şeyleri doğrulayarak uzaklaşmaya eğilimlidirler. Neden sadece @ ve en az bir tane olduğunu kontrol etmiyoruz. ve bazı basit minimum uzunlukları karşılar. Sahte bir e-posta girmeniz ve yine de geçerli herhangi bir normal ifadeyle eşleşmeniz önemsizdir. Yanlış pozitiflerin yanlış negatiflerden daha iyi olduğunu tahmin ediyorum.


1
Evet, ama hangi RFC? :) Bu [RFC ‐ 5322 – doğrulayıcı] ( stackoverflow.com/questions/201323/… ) yalnızca kırk satır uzunluğundadır.
tchrist

14
A. gerekli değil. Bir TLD'nin e-posta adresleri olabilir veya bir IPv6 adresi olabilir
Sijmen Mulder

1
RFC'ler hikayenin sonu değil: ICANN artık 'dotless' alanlara izin vermiyor: icann.org/news/announcement-2013-08-30-tr
Synchro

64

Hangi karakterlere izin verildiğine karar verirken, lütfen afrofil ve tireli arkadaşlarınızı hatırlayın. Şirketimin İK sisteminden adımı kullanarak e-posta adresimi oluşturması üzerinde hiçbir kontrole sahip değilim. Soyadımdaki kesme işaretini de içeriyor. E-posta adresimin "geçersiz" olması nedeniyle bir web sitesi ile kaç kez etkileşime girmemin engellendiğini size söyleyemem.


4
Bu, bir kişinin adına neyin izin verildiğine ve neye izin verilmediğine dair garantisiz varsayımlar yapan programlarda çok yaygın bir sorundur. Bu tür varsayımlar yapılmamalıdır, sadece ilgili RFC (ler) in yapması gereken herhangi bir karakteri kabul etmesi gerekir.
tchrist

4
Evet. Özellikle e-posta adreslerindeki büyük harfleri reddeden programcılara karşı çileden çıkıyorum! Aptal ve / veya tembel.
PhiLho

63

Bu normal ifade Perl'in Email :: Valid kütüphanesinden. En doğru olduğuna inanıyorum, tüm 822 ile eşleşiyor. O'Reilly kitabındaki düzenli ifadeye dayanıyor:

Düzenli ifade Jeffrey Friedl'in Düzenli İfadelerde Mastering örneği kullanılarak oluşturulmuştur ( http://www.ora.com/catalog/regexp/ ).

$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 Ayrıca ne yaptığını anlamak için bir regex ustası olmanız gerekir
Chris McGrath

45

PHP'de yazarken, e-postalar için PHP yerleşik doğrulamasını kullanmanızı öneririm.

filter_var($value, FILTER_VALIDATE_EMAIL)

5.3.6'dan daha düşük bir php sürümü kullanıyorsanız lütfen bu sorunun farkında olun: https://bugs.php.net/bug.php?id=53091

Bu buid-in doğrulama nasıl çalışır hakkında daha fazla bilgi istiyorsanız, buraya bakın: PHP'nin filter_var FILTER_VALIDATE_EMAIL gerçekten çalışıyor mu?


tam olarak ne söyleyeceğime oy verdim. IDN'leri işlemez, ancak önceden cezalandırma koduna dönüştürmek bunu çözer. PHP> = 5.3 bunun için idn_to_ascii () işlevine sahiptir. Bir e-postayı doğrulamanın en iyi ve en kolay yollarından biri.
Taylor


42

Kendi düzenli ifademle yaratmayı asla zahmet etmem, çünkü başka birinin daha iyi bir versiyona sahip olması ihtimali vardır. Ben her zaman beğenime bir tane bulmak için regexlib kullanın.


1
Bu, uzunluk ve içerik için işaretlendi, ancak 41 oyla hala iyi bir katkı ve silinmemelidir.
Will

37

Gerçekten kullanışlı olan biri yok.
Benim bazı konuları görüşmek İş'in orada e-posta adresi doğrulama için bir php kütüphanesi cevap? , ayrıca tartışıldı e-posta adresinin Regexp tanınması zor?

Kısacası, tek, kullanışlı bir regex'in uygun bir iş yapmasını beklemeyin. Ve en iyi normal ifade, bir e-postanın geçerliliğini değil sözdizimini doğrular (jhohn@example.com doğrudur, ancak büyük olasılıkla geri dönecektir ...).


Yanılıyorsam beni düzeltin ama PHP'nin PCRE kalıpları kullandığına inanıyorum. Eğer öyleyse, Abigail'in RFC 5322 modeline benzer bir şey yapabilmelisiniz .
tchrist

@tchrist: PCRE'nin bu sözdizimini yakalayıp yakalamadığından emin değilim (keşfettiğim). Eğer öyleyse, PHP'nin PCRE'sinin PCRE'nin bu versiyonunu yakalayıp yakalamadığından emin değilim ... Eh, bu sözdizimini doğru bir şekilde anlarsam, yine de bir regex'ten çok daha net ve eksiksiz bir PEG ayrıştırıcı kullanabilirsiniz.
PhiLho

PCRE bunu yakaladı, ancak PHP belki PCRE'yi yakalamadı. ☹
tchrist

36

En azından geçerli herhangi bir e-posta adresini reddetmeyecek basit bir düzenli ifade, bir şey, ardından bir @ işareti, ardından da bir nokta ve en az 2 şey izleyecektir. Hiçbir şeyi reddetmez, ancak teknik özellikleri inceledikten sonra geçerli ve reddedilecek herhangi bir e-posta bulamıyorum.

e-posta = ~ /.+@[^@]+\.[^@]{2,}$/


3
Aradığım şey buydu. Çok kısıtlayıcı değil, ancak sadece 1 @ olduğundan emin oluyoruz (bir listeyi ayrıştırdığımız ve eksik virgül olmadığından emin olmak istediğimizden). Bilginize, tırnak işaretleri arasındaysa solda bir @ olabilir: Valid_email_addresses , ama oldukça saçak.
Josh

2
Kullandıktan sonra, tam olarak çalışmadığını fark etti. /^[^@]+@[^@]+\.[^@]{2}[^@]*$/ aslında 1 @ işaretini denetler. Normal ifadeniz, sonunda. * Nedeniyle birden çok noktaya izin verir.
Josh

1
Sağ. Tüm geçersiz reddetmeye çalışmıyorum, sadece geçerli bir e-posta adresini reddetmekten kaçının.
Spig

1
Bunu kullanmak çok daha iyi olurdu: /^[^@]+@[^@]+\.[^@]{2,4}$/2 ila 4 olmayan @ karakteriyle bitmesini sağlamak. @Josh'un işaret ettiği gibi, artık ekstra bir @'ye izin veriyor. Ancak bunu şu şekilde de değiştirebilirsiniz: /^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/çünkü tüm üst düzey alan adları aZ karakteridir. Eğer yerini alabilir 4ile 5ya da daha üst seviye alan adları gelecekte uzun olması için izin de.
FLY

@FLY, ka @ foo. doğru döndürür. Standartlara uygun mu?
15:31

29

JQuery Validation eklentisi tarafından kullanılanı kullanabilirsiniz:

/^((([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

bu iyi bir iş çıkarmış gibi görünüyor. İzin verdi: a-b'c_d.e@f-g.hancak a-b'c_d.@f-g.handa-b'c_d.e@f-.h
dsdsdsdsd

25

Bir e-posta adresini doğrulamak için en iyi düzenli ifadenin en kapsamlı değerlendirmesi için lütfen bu bağlantıya bakın; " Normal İfadeleri Doğrulama E-posta Adresini Karşılaştırma "

Referans amacıyla şu anki en iyi ifade:

/^([\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: Bu bağlantı gerçekten doğru değil. E-posta adreslerini doğrulamak için mükemmel bir kalıp bulunamayacağı ifadesi, açıkça hatalıdır. Sen can , ama emin sen sağ aşağı mektuba RFC takip ettiğini yapmak zorunda. Ve doğru RFC'yi de seçmelisiniz.
tchrist

"En iyi" şu anda java regex ile çalışmaz - dizeden düzgün bir şekilde kaçtıktan ve dönüştürüldükten sonra bile.
Eric Chen

23

Latince olmayan (Çince, Arapça, Yunanca, İbranice, Kiril vb.) Alan adlarına yakın gelecekte izin verileceğinden bahsetmiyoruz bile . Herkes kullanılan e-posta normal ifadesini değiştirmek zorundadır, çünkü bu karakterler kesinlikle [a-z]/ine kapsamına girmez \w. Hepsi başarısız olacak.

Sonuçta , e-posta adresini doğrulamanın en iyi yolu , adresi doğrulamak için söz konusu adrese bir e-posta göndermektir . E-posta adresi kullanıcı kimlik doğrulamasının bir parçasıysa (kayıt / giriş / vb.), Kullanıcı aktivasyon sistemi ile mükemmel bir şekilde birleştirebilirsiniz. Belirtilen e-posta adresine benzersiz bir etkinleştirme anahtarı olan bir bağlantı içeren bir e-posta gönderiyoruz ve yalnızca kullanıcı e-postadaki bağlantıyı kullanarak yeni oluşturulan hesabı etkinleştirdiğinde oturum açmaya izin veriyoruz.

Normal ifadenin amacı, kullanıcı arayüzünde kullanıcıyı belirtilen e-posta adresinin doğru biçimde görünmediğini hızlı bir şekilde bilgilendirmekse, en iyisi, temel olarak aşağıdaki normal ifadeyle eşleşip eşleşmediğini kontrol etmektir:

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

Bu kadar basit. Neden dünyada ve isimde kullanılan karakterleri önemsesin ki? Sunucunun değil, geçerli bir e-posta adresi girmek müşterinin sorumluluğundadır. İstemci gibi sözdizimsel olarak geçerli bir e-posta adresi girse bile aa@bb.cc, bu yasal bir e-posta adresi olduğunu garanti etmez. Bunu hiç bir regex karşılayamaz.


4
Bir kimlik doğrulama mesajı göndermenin genellikle bu tür şeyler için en iyi yol olduğunu kabul ediyorum, sözdizimsel olarak doğru ve geçerli aynı değil. "Onay" için e-posta adresimi iki kez yazmak için yazdığımda hayal kırıklığına uğradım. Sadece birincisini ikincisine kopyalarım, gittikçe daha fazla kullanılıyor gibi görünüyor.
PeteT

Katılıyorum! ama bu regex spaces, @.örneğin sonra izin çünkü geçerli olduğunu sanmıyorum . test@test.ca com netyukarıdaki normal ifadeyi kullanarak geçerli bir e-postayı, geçersiz olarak döndürülmesi gerektiği şeklinde düşünür.
CB4

20

HTML5 Spec anlaşılacağı e-posta adreslerini doğrulamak için basit 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])?)*$/

Bu kasıtlı olarak RFC 5322 ile uyumlu değildir .

Not: Bu gereklilik, bir olan kasıtlı ihlali ait RFC 5322 (daha önce aynı anda çok katı olduğunu, e-posta adresleri için bir söz dizimi tanımlar, @(sonra çok belirsiz karakteri), @yorum, boşluk karakterlerini izin karakteri) ve çok gevşek ( ve alıntılanan dizeler çoğu kullanıcıya tanıdık gelmez) burada pratik olarak kullanılabilir.

Toplam uzunluk, RFC 3696 errata 1690'a göre 254 karakterle sınırlı olabilir .


En iyi cevap! İşte w3 önerisine bir bağlantı: w3.org/TR/html5/forms.html#valid-e-mail-address Bu normal ifade birçok tarayıcı tarafından benimsenmiştir.
Ryan Taylor

3
Bu ÇOK en iyi cevap değil! Bu model, bu tamamen geçersiz adres eşleşir: invalid@emailaddress. Ben kullanmadan önce dikkat ve çok test teşvik ediyorum!
Sheridan

@Sheridan, HTML5 spesifikasyonuyla ilgili bir sorun olduğunu düşünüyorsanız, burada bir sorun oluşturabilirsiniz: github.com/w3c/html/issues
Luna

Bu, stackoverflow.com/a/8829363 üzerinde fazla bir şey eklemez ve IMHO, bir düzenleme veya yorum olarak daha iyi olur.

example @ localhost geçerlidir, ancak gerçek dünya uygulaması için bir alan adı uzantısını zorunlu kılmak isteyebilirsiniz, bunu yapmak için yapmanız gereken tek şey final * 'i +' ya değiştirmek (desenin o kısmını 0+ 'dan 1+' ya değiştirmek) )
Mitch Satchwell

15

Canlı bir gösteri için, aşağıdaki canavar oldukça iyidir, ancak sözdizimsel olarak geçerli tüm e-posta adreslerini doğru bir şekilde tanımıyor: dört düzey derinliğe kadar iç içe yorumları tanır.

Bu bir ayrıştırıcı için bir iştir, ancak bir adres sözdizimsel olarak geçerli olsa bile, yine de teslim edilemeyebilir. Bazen "Hey, hepiniz, ee-bizi izleyin!"

// 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

Resmi standart RFC 2822'ye göre geçerli e-posta normal ifadesi

(?:[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 ile kullanmak istiyorsanız gerçekten çok kolay

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
Normal ifadeniz, bazı kullanıcılar için sinir bozucu olabilecek ilk büyük harfi içermiyor, örneğin Leonardo.davinci@gmail.com . Bunun yerine bunu kullanın:(?:[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 Teşekkürler, lütfen cevabı düzenleyin, değişikliği kabul edeceğim.
AZ_

Cevabınıza bu değişikliği eklerseniz artık RFC 2822 olmayacak, bu yüzden doğru olup olmadığını bilmiyorum.
Kebab Krabby

11

İşte kullandığım PHP. Bu çözümü, burada başka bir yorumcu tarafından beyan edildiği gibi "yanlış pozitifler yanlış negatiflerden daha iyi" ruhuyla seçtim VE yanıt sürenizi ve sunucu yükünü düşük tutmak için ... gerçekten sunucu kaynaklarını boşa harcamasına gerek yok en basit kullanıcı hatasını ayıklayacağı zaman düzenli bir ifade. İsterseniz bunu bir test e-postası göndererek takip edebilirsiniz.

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

1
a) "Atık sunucu kaynakları" sonsuzdur, ancak çok eğimliyseniz, bunu JS ile istemci tarafında yapabilirsiniz. b) Kayıt postası göndermeniz gerekir ve kullanıcı bana @ forgotthedotcom girer? "Çözümünüz" başarısız olur ve bir kullanıcıyı kaybedersiniz.
johnjohn

a) JavaScript devre dışı bırakıldığında başarısız olacak bir JS doğrulamasına güvenmek de en iyi fikir gibi görünmüyor (sadece btw)
auco

11

RFC 5322 standardı:

Nokta-atom yerel-bölüm, tırnaklı-dize yerel-bölüm, eski (karışık nokta-atom ve tırnak-dize) yerel-bölüm, etki alanı adı etki alanı, (IPv4, IPv6 ve IPv4-eşlemeli IPv6 adresi) etki alanı değişmez alanı, ve (iç içe) 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 standardı:

Nokta atomlu yerel parça, tırnak içine alınmış dize yerel kısmı, etki alanı adı etki alanı ve (IPv4, IPv6 ve IPv4 eşlemeli IPv6 adresi) etki alanı değişmez alanına izin verir.

'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){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'

Temel:

Nokta atomlu yerel parça ve alan adı alanına izin verir (TLD 2-6 alfabetik karakterle sınırlı en az iki alan adı etiketi gerektirir).

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

Şeytan dili nedir ?? Bir /Dbayrak görüyorum ve tek tırnakla alıntı yaptınız, ancak deseni sınırlamak için eğik çizgiler kullandınız mı? Perl değil ve PCRE olamaz. Bu yüzden PHP mi? İnanıyorum ki bunlar tekerrür gibi izin veren tek üçü (?1).
tchrist

PCRE kullanan PHP'de. Eğik çizgiler yalnızca parantez, köşeli parantezler ve elbette eğik çizgiler ve tek tırnak işaretleri gibi özel karakterleri sınırlamak için kullanılır. / D bayrağı, bilmiyorsanız, dizenin sonuna bir satırsonu eklenmesini engellemektir.
MichaelRushton

9

4 karakter TLD'ye "izin veremeyeceğiniz" garip. Sen insanları yasakladıklarını .info ve .name ve uzunluk sınırlaması durdurma .travel ve .museum ama evet, onlar 2 karakter TLD'leri ve 3 karakter TLD'leri daha az yaygındır.

Büyük harfli alfabelere de izin vermelisiniz. E-posta sistemleri yerel kısmı ve alan adını normalleştirecektir.

Alan adı regex'iniz için alan adı '-' ile başlayamaz ve '-' ile bitemez. Dash yalnızca arada kalabilir.

PEAR kitaplığını kullandıysanız, posta işlevlerini kontrol edin (tam adı / kitaplığı unuttum). Bir işlevi çağırarak e-posta adresini ve RFC822'deki tanıma göre e-posta adresini doğrulayabilirsiniz.


2
@Joseph Yee: RFC 822 biraz tarihli değil mi?
tchrist

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;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.