Wie überprüfe ich eine E-Mail-Adresse mit einem regulären Ausdruck?


3311

Im Laufe der Jahre habe ich langsam einen regulären Ausdruck entwickelt , der die meisten E-Mail-Adressen korrekt validiert, vorausgesetzt, sie verwenden keine IP-Adresse als Serverteil.

Ich benutze es in mehreren PHP-Programmen und es funktioniert die meiste Zeit. Von Zeit zu Zeit werde ich jedoch von jemandem kontaktiert, der Probleme mit einer Site hat, die sie verwendet, und am Ende muss ich einige Anpassungen vornehmen (zuletzt wurde mir klar, dass ich keine 4-Zeichen-TLDs zulasse).

Was ist der beste reguläre Ausdruck, den Sie zum Überprüfen von E-Mails haben oder gesehen haben?

Ich habe mehrere Lösungen gesehen, die Funktionen verwenden, die mehrere kürzere Ausdrücke verwenden, aber ich hätte lieber einen langen komplexen Ausdruck in einer einfachen Funktion anstelle mehrerer kurzer Ausdrücke in einer komplexeren Funktion.



5
Der reguläre Ausdruck, der überprüfen kann, ob eine IDNA korrekt formatiert ist, passt nicht in den Stapelaustausch. (Die Regeln zur
Jasen


Die regulären Ausdrücke können variabel sein, da in einigen Fällen ein E-Mail-Con ein Leerzeichen enthalten kann und in anderen Fällen keine Leerzeichen.
23gǻňạcểơửṩ

Antworten:


2439

Der vollständig RFC 822-kompatible Regex ist aufgrund seiner Länge ineffizient und unklar. Glücklicherweise wurde RFC 822 zweimal abgelöst und die aktuelle Spezifikation für E-Mail-Adressen lautet RFC 5322 . RFC 5322 führt zu einem regulären Ausdruck, der verstanden werden kann, wenn er einige Minuten lang untersucht wird, und der für den tatsächlichen Gebrauch effizient genug ist.

Ein RFC 5322-kompatibler regulärer Ausdruck befindet sich oben auf der Seite unter http://emailregex.com/ , verwendet jedoch das im Internet schwebende IP-Adressmuster mit einem Fehler, der einen 00der vorzeichenlosen Byte-Dezimalwerte in a zulässt Punktgetrennte Adresse, die illegal ist. Der Rest scheint mit der RFC 5322-Grammatik übereinzustimmen und besteht mehrere Tests unter Verwendung von grep -PoDomainnamen, IP-Adressen, fehlerhaften und Kontonamen mit und ohne Anführungszeichen.

Wenn 00wir den Fehler im IP-Muster korrigieren , erhalten wir einen funktionierenden und ziemlich schnellen regulären Ausdruck. (Kratzen Sie die gerenderte Version und nicht den Abschlag für den tatsächlichen Code.)

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

oder:

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

Hier ist ein Diagramm der Finite-State-Maschine für den obigen regulären Ausdruck, das klarer ist als der reguläre Ausdruck selbst Geben Sie hier die Bildbeschreibung ein

Die komplexeren Muster in Perl und PCRE (Regex-Bibliothek, die z. B. in PHP verwendet wird) können RFC 5322 ohne Probleme korrekt analysieren . Python und C # können das auch, aber sie verwenden eine andere Syntax als die ersten beiden. Wenn Sie jedoch gezwungen sind, eine der vielen weniger leistungsfähigen Mustervergleichssprachen zu verwenden, ist es am besten, einen echten Parser zu verwenden.

Es ist auch wichtig zu verstehen, dass die Validierung gemäß RFC absolut nichts darüber aussagt, ob diese Adresse tatsächlich in der angegebenen Domain vorhanden ist oder ob die Person, die die Adresse eingibt, ihr wahrer Eigentümer ist. Auf diese Weise melden sich andere ständig bei Mailinglisten an. Eine Korrektur, die eine ausgefallenere Art der Validierung erfordert, bei der dieser Adresse eine Nachricht gesendet wird, die ein Bestätigungstoken enthält, das auf derselben Webseite wie die Adresse eingegeben werden soll.

Bestätigungstoken sind der einzige Weg zu wissen, dass Sie die Adresse der Person erhalten haben, die sie eingibt. Aus diesem Grund verwenden die meisten Mailinglisten diesen Mechanismus jetzt, um Anmeldungen zu bestätigen. Schließlich kann jeder etwas ablegen president@whitehouse.gov, und das wird sogar als legal angesehen, aber es ist wahrscheinlich nicht die Person am anderen Ende.

Für PHP sollten Sie nicht das unter Validieren einer E-Mail-Adresse mit PHP angegebene Muster verwenden. Der richtige Weg, aus dem ich zitiere:

Es besteht die Gefahr, dass die allgemeine Verwendung und die weit verbreitete schlampige Codierung einen De-facto-Standard für E-Mail-Adressen festlegen, der restriktiver ist als der aufgezeichnete formale Standard.

Das ist nicht besser als alle anderen Nicht-RFC-Muster. Es ist nicht einmal klug genug, um mit RFC 822 umzugehen , geschweige denn mit RFC 5322. Dies ist jedoch der Fall .

Wenn Sie ausgefallen und pedantisch werden möchten, implementieren Sie eine vollständige State Engine . Ein regulärer Ausdruck kann nur als rudimentärer Filter fungieren. Das Problem bei regulären Ausdrücken besteht darin, dass es aus Sicht des Benutzers nur unhöflich und unhöflich ist, jemandem mitzuteilen, dass seine perfekt gültige E-Mail-Adresse ungültig ist (falsch positiv), weil Ihr regulärer Ausdruck damit nicht umgehen kann. Eine State Engine für diesen Zweck kann E-Mail-Adressen, die ansonsten als ungültig gelten würden, sowohl validieren als auch korrigieren, da sie die E-Mail-Adresse gemäß jedem RFC zerlegt. Dies ermöglicht eine möglicherweise angenehmere Erfahrung, wie z

Die angegebene E-Mail-Adresse 'myemail @ address, com' ist ungültig. Meinten Sie "myemail@address.com"?

Siehe auch Überprüfen von E-Mail-Adressen , einschließlich der Kommentare. Oder Vergleichen der E-Mail-Adresse zur Überprüfung regulärer Ausdrücke .

Visualisierung regulärer Ausdrücke

Debuggex-Demo


179
Sie sagten: "Es gibt keinen guten regulären Ausdruck." Ist dies allgemein oder spezifisch für die Überprüfung der E-Mail-Adresse?
Tomalak

37
@Tomalak: nur für E-Mail-Adressen. Wie Bortzmeyer sagte, ist der RFC extrem kompliziert
Luk

37
Der von Ihnen erwähnte Artikel im Linux-Journal ist in mehrfacher Hinsicht sachlich falsch. Insbesondere hat Lovell die Errata in RFC3696 offensichtlich nicht gelesen und wiederholt einige der Fehler in der veröffentlichten Version des RFC. Mehr hier: dominicsayers.com/isemail
Dominic Sayers

9
Jeff Atwood hat eine schöne Regex in diesem Blog-Beitrag, um alle gültigen E-Mail-Adressen zu validieren: Codinghorror.com/blog/2005/02/regex-use-vs-regex-abuse.html
CMircea

5
Beachten Sie, dass die aktuelle HTML5-Spezifikation einen regulären Ausdruck und ABNF für die Validierung von E-Mail-Eingaben enthält, die absichtlich restriktiver sind als die ursprünglichen RFCs.
Synchro

746

Sie sollten keine regulären Ausdrücke verwenden, um E-Mail-Adressen zu überprüfen.

Verwenden Sie stattdessen die MailAddress- Klasse wie folgt :

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

Die MailAddressKlasse verwendet einen BNF-Parser, um die Adresse gemäß RFC822 vollständig zu validieren.

Wenn Sie die MailAddresszur Überprüfung der E-Mail-Adresse verwenden möchten, beachten Sie, dass dieser Ansatz auch den Anzeigenamen-Teil der E-Mail-Adresse akzeptiert und möglicherweise nicht genau das ist, was Sie erreichen möchten. Beispielsweise werden diese Zeichenfolgen als gültige E-Mail-Adressen akzeptiert:

  • "user1@hotmail.com; user2@gmail.com"
  • "user1@hotmail.com; user2@gmail.com; user3@company.com"
  • "Benutzeranzeigename user3@company.com"
  • "user4 @ company.com"

In einigen dieser Fälle wird nur der letzte Teil der Zeichenfolgen als Adresse analysiert. der Rest davor ist der Anzeigename. Um eine einfache E-Mail-Adresse ohne Anzeigenamen zu erhalten, können Sie die normalisierte Adresse mit Ihrer ursprünglichen Zeichenfolge vergleichen.

bool isValid = false;

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

Darüber hinaus wird eine Adresse mit einem Punkt am Ende wie user@company.auch von MailAddress akzeptiert.

Wenn Sie wirklich einen regulären Ausdruck verwenden möchten, finden Sie hier :

(?: (?: \ 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
Sie werden feststellen, dass die MailAddress-Klasse in .NET 4.0 E-Mail-Adressen weitaus besser validieren kann als in früheren Versionen. Ich habe einige wesentliche Verbesserungen vorgenommen.
Jeff Tucker

7
Ich denke, es funktioniert irgendwie ... nicht ... für einfachere IDs. a @ b wird nicht validiert. ar@b.com stimmt nur überein, bis ar @ b, das .com nicht übereinstimmt. Allerdings funktioniert so etwas wie "Ich bin ich" @ [10.10.10.10]! :)
Raze

5
Seien Sie gewarnt, dass diese RFC-kompatiblen Regex-Validatoren viele E-Mail-Adressen durchlassen, die Sie wahrscheinlich nicht akzeptieren möchten, z. B. "a <body / onload = alert (' lol.com?'+document.cookies ) @aa> " Dies
Matthew Lock

9
@ MatthewLock: Das ist nicht schlimmer als fake@not-a-real-domain.name. Sie dürfen sich nicht auf die E-Mail-Validierung verlassen, um XSS zu verhindern.
SLaks

10
@MatthewLock: Nein . Sie müssen entkommen SQL - Abfragen (oder, besser noch, verwenden Parameter). Desinfektion ist keine angemessene Verteidigung.
SLaks

536

Diese Frage wird häufig gestellt, aber ich denke, Sie sollten einen Schritt zurücktreten und sich fragen, warum Sie E-Mail-Adressen syntaktisch validieren möchten. Was ist der Vorteil wirklich?

  • Es werden keine häufigen Tippfehler abgefangen.
  • Es hindert Personen nicht daran, ungültige oder erfundene E-Mail-Adressen oder die Adresse einer anderen Person einzugeben.

Wenn Sie überprüfen möchten, ob eine E-Mail korrekt ist, haben Sie keine andere Wahl, als eine Bestätigungs-E-Mail zu senden und den Benutzer darauf antworten zu lassen. In vielen Fällen werden Sie haben eine Bestätigungsmail ohnehin aus Sicherheitsgründen oder aus ethischen Gründen (so kann man nicht zB Zeichen jemand bis zu einem Dienst gegen ihren Willen) zu senden.


92
Es könnte sich lohnen zu überprüfen, ob sie in einer clientseitigen Validierung etwas @ etwas in das Feld eingegeben haben, um einfache Fehler zu erkennen - aber im Allgemeinen haben Sie Recht.
Martin Beckett

8
Martin, ich habe dir eine +1 gegeben, nur um später zu lesen, dass foobar @ dk eine gültige E-Mail ist. Es wäre nicht schön, aber wenn Sie sowohl RFC-konform als auch mit gesundem Menschenverstand arbeiten möchten, sollten Sie Fälle wie diesen erkennen und den Benutzer bitten, die Richtigkeit zu bestätigen.
Philfreo

106
@olavk: Wenn jemand einen Tippfehler eingibt (zB :) me@hotmail, erhält er offensichtlich keine Bestätigungs-E-Mail und wo sind sie dann? Sie sind nicht mehr auf Ihrer Website und fragen sich, warum sie sich nicht anmelden konnten. Nein, das sind sie nicht - sie haben dich völlig vergessen. Wenn Sie jedoch nur eine grundlegende Überprüfung der Gesundheit mit einem regulären Ausdruck durchführen können, während sie noch bei Ihnen sind, können sie diesen Fehler sofort erkennen und Sie haben einen zufriedenen Benutzer.
Nickf

5
@ JacquesB: Sie machen einen ausgezeichneten Punkt. Nur weil es die Musterung gemäß RFC besteht, heißt das nicht, dass es wirklich die Adresse des Benutzers ist. Ansonsten president@whitehouse.govweisen alle diese Adressen auf einen sehr netbusy Oberbefehlshaber hin. :)
tchrist

39
Es muss nicht schwarz oder weiß sein. Wenn die E-Mail falsch aussieht, teilen Sie dies dem Benutzer mit. Wenn der Benutzer dennoch fortfahren möchte, lassen Sie ihn. Erzwingen Sie den Benutzer nicht, sich an Ihre Regex anzupassen, sondern verwenden Sie Regex als Werkzeug, damit der Benutzer weiß, dass möglicherweise ein Fehler vorliegt.
Ninjaneer

354

Es hängt alles davon ab, wie genau Sie sein möchten. Für meine Zwecke, bei denen ich nur versuche, Dinge wie bob @ aol.com(Leerzeichen in E-Mails) oder steve(überhaupt keine Domain) oder mary@aolcom(kein Zeitraum vor .com) fernzuhalten , verwende ich

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

Sicher, es wird mit Dingen übereinstimmen, die keine gültigen E-Mail-Adressen sind, aber es geht darum, häufig auftretende einfache Fehler zu erhalten.

Es gibt eine beliebige Anzahl von Änderungen, die an diesem regulären Ausdruck vorgenommen werden können (und einige sind in den Kommentaren zu dieser Antwort enthalten), aber es ist einfach und leicht zu verstehen und ein guter erster Versuch.


6
Es stimmt nicht mit foobar @ dk überein, einer gültigen und funktionierenden E-Mail-Adresse (obwohl wahrscheinlich die meisten Mailserver diese nicht akzeptieren oder etwas hinzufügen werden.)
bortzmeyer

3
Ja, es wird. Ich schlage vor, Sie versuchen es selbst. $ perl -le'print q{foo@bar.co.uk} = ~ /^\S+@\S+\.\S+$/? q {Y}: q {N} '
Andy Lester

7
@ Richard: .ist enthalten in \S.
David Thornley

43
JJJ: Ja, es wird viel Mist passen. Es passt auch zu & $ * # $ (@ $ 0 (%)) $ #.) & *) (* $. Für mich geht es mir mehr darum, den seltsamen Tippfehler zu fangen, mary@aolcomals dass ich kompletter Müll bin YMMV.
Andy Lester

5
Nur um die @Zeichen zu kontrollieren : /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/ jsfiddle.net/b9chris/mXB96
Chris Moschini

338

Es hängt davon ab, was Sie am besten meinen: Wenn Sie über das Abrufen jeder gültigen E-Mail-Adresse sprechen, verwenden Sie Folgendes:

(?:(?:\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 ) Wenn Sie nach etwas Einfacherem suchen, das aber die meisten gültigen E-Mail-Adressen abfängt, versuchen Sie Folgendes:

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

EDIT: Über den Link:

Dieser reguläre Ausdruck überprüft nur Adressen, bei denen Kommentare entfernt und durch Leerzeichen ersetzt wurden (dies wird vom Modul durchgeführt).


10
Es stimmt nicht mit allen Adressen überein, einige müssen zuerst transformiert werden. Über den Link: "Dieser reguläre Ausdruck überprüft nur Adressen, bei denen Kommentare entfernt und durch Leerzeichen ersetzt wurden (dies wird vom Modul durchgeführt)."
Chas. Owens

47
Können Sie mir ein Beispiel für einige geben email address, die fälschlicherweise die zweite durchlaufen, aber von der längeren Regex erfasst werden?
Lazer

4
Obwohl ich es einmal geliebt habe, ist das ein RFC 822-Validator, kein RFC 5322 .
Tchrist

24
@Lazer in..valid @ example.com wäre ein einfaches Beispiel. Sie dürfen nicht zwei aufeinanderfolgende nicht zitierte Punkte im lokalen Teil haben.
Randal Schwartz

5
@Mikhail Perl, aber Sie sollten es eigentlich nicht verwenden.
Gute Person

287

[AKTUALISIERT] Ich habe alles, was ich über die Validierung von E-Mail-Adressen weiß, hier zusammengefasst: http://isemail.info , das jetzt nicht nur Probleme mit E-Mail-Adressen validiert, sondern auch diagnostiziert. Ich stimme vielen Kommentaren hier zu, dass die Validierung nur ein Teil der Antwort ist. Siehe meinen Aufsatz unter http://isemail.info/about .

is_email () bleibt meines Wissens der einzige Validator, der Ihnen definitiv sagt, ob eine bestimmte Zeichenfolge eine gültige E-Mail-Adresse ist oder nicht. Ich habe eine neue Version unter http://isemail.info/ hochgeladen.

Ich habe Testfälle von Cal Henderson, Dave Child, Phil Haack, Doug Lovell, RFC5322 und RFC 3696 zusammengestellt. Insgesamt 275 Testadressen. Ich habe all diese Tests gegen alle freien Validatoren durchgeführt, die ich finden konnte.

Ich werde versuchen, diese Seite auf dem neuesten Stand zu halten, wenn Leute ihre Validatoren verbessern. Vielen Dank an Cal, Michael, Dave, Paul und Phil für ihre Hilfe und Zusammenarbeit bei der Zusammenstellung dieser Tests und für die konstruktive Kritik an meinem eigenen Validator .

Die Leute sollten sich insbesondere der Errata gegen RFC 3696 bewusst sein . Drei der kanonischen Beispiele sind tatsächlich ungültige Adressen. Die maximale Länge einer Adresse beträgt 254 oder 256 Zeichen, nicht 320.


Dieser Validator scheint ebenfalls korrekt zu sein. [... die Zeit vergeht ...] Hm, es sieht so aus, als wäre es nur RFC 5322, nicht 3693 oder Errata dazu.
Tchrist

1
Sehr schön. Hier bekommen wir nicht nur einen schönen Aufsatz, sondern auch einen Validierungstester sowie eine Bibliothek zum Herunterladen. Gute Antwort!
bgmCoder

Ihr Validator unterstützt keinen Punycode (RFC 3492). name@öäü.at kann eine gültige Adresse sein. (es übersetzt zu name@xn--4ca9at.at)
Josef sagt Reinstate Monica

Hallo @Josef. Sie sollten versuchen, zu validieren, name@xn--4ca9at.atda es bei diesem Code um Validierung und nicht um Interpretation geht. Wenn Sie einen Punycode-Übersetzer hinzufügen möchten, nehme ich gerne eine Pull-Anfrage unter github.com/dominicsayers/isemail
Dominic Sayers an.

266

Gemäß der W3C HTML5-Spezifikation :

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

Kontext:

Eine gültige E-Mail-Adresse ist eine Zeichenfolge, die der ABNF-Produktion entspricht […].

Hinweis: Diese Anforderung stellt eine vorsätzliche Verletzung von RFC 5322 dar , das eine Syntax für E-Mail-Adressen definiert, die gleichzeitig zu streng (vor dem @ -Zeichen), zu vage (nach dem @ -Zeichen) und zu lasch ( Hier können Kommentare, Leerzeichen und zitierte Zeichenfolgen auf eine Weise verwendet werden, die den meisten Benutzern unbekannt ist.

Der folgende JavaScript- und Perl-kompatible reguläre Ausdruck ist eine Implementierung der obigen Definition.

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/


12
Das ist interessant. Es ist eine Verletzung von RFC, aber eine vorsätzliche und es macht sesne. Beispiel aus der Praxis: Google Mail ignoriert Punkte im Teil vor @. Wenn Ihre E-Mail also test@gmail.com lautet, können Sie E-Mails an test senden. @ Gmail.com oder test .... @ gmail.com. Beide Adressen sind laut RFC ungültig, aber in der realen Welt gültig.
Valentinas

Ich denke, der letzte Teil sollte '+' anstelle von '*' sein: ^ [a-zA-Z0-9.! # $% & '* + / =? ^ _ `{|} ~ -] + @ [a- zA-Z0-9 -] + (?: \. [a-zA-Z0-9 -] +) + $
mmmmmm

7
@mmmmmm john.doe@localhostist gültig. Sicher, in einer realen Anwendung (dh einer Community) möchte ich, dass Ihr Vorschlag * durch +
rabudde

3
@valentinas Eigentlich schließt der RFC diese lokalen Teile nicht aus, aber sie müssen in Anführungszeichen gesetzt werden. "test...."@gmail.comist laut RFC vollkommen gültig und semantisch äquivalent zu test....@gmail.com.
Rinke

Beim Versuch, E-Mails mit Python über das Relay meines Unternehmens zu senden, wird eine Fehlermeldung angezeigt, wenn ich versuche, an eine Adresse mit einem. @ Oder .. @ zu senden. Eigentlich ist das auch bei einem _ @ der Fall. Ich entferne diese lieber vor dem Senden, als darauf zu vertrauen, dass der Empfänger dies tut.
ndvo

201

In Perl 5.10 oder höher ist das ganz einfach:

/(?(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
Würde gerne dies in Python sehen
tdc

4
Ich denke, dass nur eine Teilmenge des addrspecTeils für die Frage wirklich relevant ist. Wenn Sie mehr als das akzeptieren und weiterleiten, obwohl ein anderer Teil des Systems, der nicht bereit ist, vollständige RFC5822-Adressen zu akzeptieren, so ist, als wäre das Schießen Ihr eigener Fuß.
Dolmen

3
Großartig (+1), aber technisch gesehen ist es natürlich kein regulärer Ausdruck ... (was unmöglich wäre, da die Grammatik nicht regelmäßig ist).
Rinke

10
Regexes sind seit einiger Zeit nicht mehr regelmäßig. Es ist jedoch ein gültiger Perl-Regex!
10.

4
Ich habe einen Test für diesen regulären Ausdruck auf IDEone eingerichtet: ideone.com/2XFecH Es ist jedoch nicht "perfekt" fair. Würde es jemandem etwas ausmachen, sich einzuschalten? Vermisse ich etwas
Mike

159

ich benutze

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

Welches ist dasjenige, das in ASP.NET vom RegularExpressionValidator verwendet wird.


28
Boo! Meine (schlecht beratene) Adresse von !@mydomain.netwird abgelehnt.
Phrogz

3
Laut dieser Seite data.iana.org/TLD/tlds-alpha-by-domain.txt gibt es keine Domains mit nur einem einzelnen Zeichen in der obersten Ebene, z. B. " Something.c ", "Something.a". Hier ist die Version, die unterstütze mindestens 2 Zeichen: "Something.pl", "Something.us":^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
Tomasz Szulc

4
@ Wayne Whitty. Sie sind auf die Hauptfrage gestoßen, ob die überwiegende Mehrheit der Adressen oder ALLE Adressen berücksichtigt werden sollen, einschließlich solcher, die niemand verwenden würde, außer zum Testen der E-Mail-Validierung.
Patanjali

@TomaszSzulc zusätzlicher Schrägstrich in Ihrer Antwort ist verwirrend, ich habe ihn gerade korrigiert und die Unterstützung für 2 Zeichen-Domainnamen funktioniert, ^ \ w + ([- +. '] \ W +) * @ \ w + ([-.] \ W +) * \. \ w {2,} ([-.] \ w +) * $
Aqib Mumtaz

2
Dies schlägt fehl, simon-@hotmail.comwas tatsächlich gültig ist (ein Kunde von uns hatte eine ähnliche Adresse). `
Simon_Weaver

142

Ich weiß nicht, was am besten ist, aber dieser ist zumindest richtig, solange die Kommentare der Adressen entfernt und durch Leerzeichen ersetzt werden.

Ernsthaft. Sie sollten eine bereits geschriebene Bibliothek zum Überprüfen von E-Mails verwenden. Der beste Weg ist wahrscheinlich, einfach eine Bestätigungs-E-Mail an diese Adresse zu senden.


2
Soweit ich weiß, sind auch einige Bibliotheken falsch. Ich erinnere mich vage, dass PHP PEAR einen solchen Fehler hatte.
Bortzmeyer

Diese Seite enthält unten einen Haftungsausschluss für einige Dinge aus der Spezifikation. dass der reguläre Ausdruck nicht unterstützt.
Chris Vest

7
Dies ist eine RFC 822-Spezifikation, keine RFC 5322- Spezifikation.
Tchrist

12
Letztendlich hat er Recht, dass die einzige Möglichkeit, eine E-Mail-Adresse wirklich zu validieren, darin besteht, eine E-Mail an sie zu senden und auf eine Antwort zu warten.
Blazemonger

109

Die E-Mail-Adressen, die ich überprüfen möchte, werden von einer ASP.NET-Webanwendung unter Verwendung des System.Net.Mail-Namespace verwendet, um E-Mails an eine Liste von Personen zu senden. Anstatt einen sehr komplexen regulären Ausdruck zu verwenden, versuche ich einfach, eine MailAddress-Instanz aus der Adresse zu erstellen. Der MailAddress-Construtor löst eine Ausnahme aus, wenn die Adresse nicht richtig gebildet wird. Auf diese Weise weiß ich, dass ich zumindest die E-Mail aus der Tür bekommen kann. Natürlich ist dies eine serverseitige Validierung, aber zumindest benötigen Sie diese trotzdem.

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
Ein guter Punkt. Selbst wenn diese Serverüberprüfung eine gültige Adresse ablehnt, ist dies kein Problem, da Sie mit dieser speziellen Servertechnologie ohnehin nicht an diese Adresse senden können. Oder Sie können versuchen, dasselbe mit einer E-Mail-Bibliothek eines Drittanbieters zu tun, die Sie anstelle der Standardtools verwenden.
Benutzer

Mir gefällt sehr, wie dies den .NET-Framework-Code nutzt - es macht keinen Sinn, das Rad neu zu erfinden. Das ist ausgezeichnet. Einfach, sauber und versichert, dass Sie die E-Mail tatsächlich senden können. Gute Arbeit.
Cory House

... ja und für diejenigen, die daran interessiert sind, wie es validiert wird, schauen Sie sich den Code in Reflector an - es gibt einiges davon - und es ist kein regulärer Ausdruck!
Tom Carter

2
Nur ein Hinweis: Die MailAddress-Klasse stimmt nicht mit RFC5322 überein, wenn Sie sie nur zur Validierung verwenden möchten (und nicht auch senden möchten. In diesem Fall handelt es sich um einen strittigen Punkt, wie oben erwähnt). Siehe: stackoverflow.com/questions/6023589/…
porges

Nur ein kleines Problem: Wenn Sie Ihren serverseitigen Validierungscode wiederverwendbarer machen möchten (entweder in diesem Fall oder allgemein), empfehle ich, args.Valuedas Feld zu verwenden, anstatt es wie txtEmail.Textfest codiert zu referenzieren . Letzteres bindet Ihren Validator an die einzelne Steuerelementinstanz, was möglicherweise in Ordnung ist, solange Sie ein einzelnes E-Mail-Feld haben, das jedoch nicht anders empfohlen wird.
Pholpar

109

Schnelle Antwort

Verwenden Sie für die Eingabevalidierung den folgenden regulären Ausdruck:

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

Mit diesem regulären Ausdruck übereinstimmende Adressen:

  • einen lokalen Teil haben (dh den Teil vor dem @ -Zeichen), der streng mit RFC 5321/5322 kompatibel ist,
  • einen Domain-Teil (dh den Teil nach dem @ -Zeichen) haben, der ein Hostname mit mindestens zwei Bezeichnungen ist, von denen jede höchstens 63 Zeichen lang ist.

Die zweite Einschränkung ist eine Einschränkung für RFC 5321/5322.

Aufwändige Antwort

Die Verwendung eines regulären Ausdrucks, der E-Mail-Adressen erkennt, kann in verschiedenen Situationen hilfreich sein: Zum Beispiel zum Scannen nach E-Mail-Adressen in einem Dokument, zum Überprüfen von Benutzereingaben oder als Integritätsbedingung für ein Datenrepository.

Es sollte jedoch beachtet werden, dass es keinen Ersatz für das Senden einer Nachricht an die Adresse gibt, wenn Sie herausfinden möchten, ob sich die Adresse tatsächlich auf ein vorhandenes Postfach bezieht. Wenn Sie nur überprüfen möchten, ob eine Adresse grammatikalisch korrekt ist, können Sie einen regulären Ausdruck verwenden. Beachten Sie jedoch, dass ""@[]es sich um eine grammatikalisch korrekte E-Mail-Adresse handelt, die sich sicherlich nicht auf ein vorhandenes Postfach bezieht.

Die Syntax von E-Mail-Adressen wurde in verschiedenen RFCs definiert , insbesondere in RFC 822 und RFC 5322 . RFC 822 sollte als "ursprünglicher" Standard und RFC 5322 als neuester Standard angesehen werden. Die in RFC 822 definierte Syntax ist die mildeste und nachfolgende Standards haben die Syntax immer weiter eingeschränkt, wobei neuere Systeme oder Dienste veraltete Syntax erkennen, aber niemals erzeugen sollten.

In dieser Antwort verstehe ich unter "E-Mail-Adresse" die addr-specDefinition in den RFCs (dh jdoe@example.org, aber nicht "John Doe"<jdoe@example.org>, noch some-group:jdoe@example.org,mrx@exampel.org;).

Es gibt ein Problem bei der Übersetzung der RFC-Syntax in reguläre Ausdrücke: Die Syntax ist nicht regulär! Dies liegt daran, dass optionale Kommentare in E-Mail-Adressen zulässig sind, die unendlich verschachtelt werden können, während die unendliche Verschachtelung nicht durch einen regulären Ausdruck beschrieben werden kann. Um nach Adressen zu suchen oder diese zu validieren, die Kommentare enthalten, benötigen Sie einen Parser oder leistungsfähigere Ausdrücke. (Beachten Sie, dass Sprachen wie Perl Konstrukte haben, um kontextfreie Grammatiken regexartig zu beschreiben.) In dieser Antwort werde ich Kommentare ignorieren und nur die richtigen regulären Ausdrücke berücksichtigen.

Die RFCs definieren Syntaxen für E-Mail-Nachrichten, nicht für E-Mail-Adressen als solche. Adressen können in verschiedenen Kopfzeilenfeldern angezeigt werden und werden hier hauptsächlich definiert. Wenn sie in Kopfzeilenfeldern angezeigt werden, können Adressen (zwischen lexikalischen Token) Leerzeichen, Kommentare und sogar Zeilenumbrüche enthalten. Semantisch hat dies jedoch keine Bedeutung. Durch Entfernen dieses Leerzeichens usw. aus einer Adresse erhalten Sie eine semantisch äquivalente kanonische Darstellung . Damit die kanonische Darstellung first. last (comment) @ [3.5.7.9]ist first.last@[3.5.7.9].

Unterschiedliche Syntaxen sollten für unterschiedliche Zwecke verwendet werden. Wenn Sie in einem (möglicherweise sehr alten) Dokument nach E-Mail-Adressen suchen möchten, empfiehlt es sich möglicherweise, die in RFC 822 definierte Syntax zu verwenden. Wenn Sie jedoch Benutzereingaben validieren möchten, können Sie die verwenden Syntax wie in RFC 5322 definiert, wahrscheinlich nur kanonische Darstellungen akzeptierend. Sie sollten entscheiden, welche Syntax für Ihren speziellen Fall gilt.

Ich verwende in dieser Antwort POSIX "erweiterte" reguläre Ausdrücke unter der Annahme eines ASCII-kompatiblen Zeichensatzes.

RFC 822

Ich kam zu dem folgenden regulären Ausdruck. Ich lade alle ein, es zu versuchen und zu brechen. Wenn Sie falsch positive oder falsch negative Ergebnisse finden, posten Sie diese bitte in einem Kommentar. Ich werde versuchen, den Ausdruck so schnell wie möglich zu korrigieren.

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

Ich glaube, dass es mit RFC 822 einschließlich der Errata voll kompatibel ist . E-Mail-Adressen werden nur in ihrer kanonischen Form erkannt. Eine Regex, die Leerzeichen erkennt (faltet), finden Sie in der folgenden Ableitung.

Die Ableitung zeigt, wie ich zu dem Ausdruck gekommen bin. Ich liste alle relevanten Grammatikregeln aus dem RFC genau so auf, wie sie erscheinen, gefolgt von der entsprechenden Regex. Wenn ein Erratum veröffentlicht wurde, gebe ich einen separaten Ausdruck für die korrigierte Grammatikregel (markiert mit "Erratum") und verwende die aktualisierte Version als Unterausdruck in nachfolgenden regulären Ausdrücken.

Wie in Absatz 3.1.4 angegeben. von RFC 822 kann ein optionaler linearer Leerraum zwischen lexikalischen Token eingefügt werden. Wo zutreffend, habe ich die Ausdrücke erweitert, um diese Regel zu berücksichtigen, und das Ergebnis mit "opt-lwsp" markiert.

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

Ich kam zu dem folgenden regulären Ausdruck. Ich lade alle ein, es zu versuchen und zu brechen. Wenn Sie falsch positive oder falsch negative Ergebnisse finden, posten Sie diese bitte in einem Kommentar. Ich werde versuchen, den Ausdruck so schnell wie möglich zu korrigieren.

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

Ich glaube, es ist voll kompatibel mit RFC 5322 einschließlich der Errata . E-Mail-Adressen werden nur in ihrer kanonischen Form erkannt. Eine Regex, die Leerzeichen erkennt (faltet), finden Sie in der folgenden Ableitung.

Die Ableitung zeigt, wie ich zu dem Ausdruck gekommen bin. Ich liste alle relevanten Grammatikregeln aus dem RFC genau so auf, wie sie erscheinen, gefolgt von der entsprechenden Regex. Für Regeln, die semantisch irrelevante (faltbare) Leerzeichen enthalten, gebe ich einen separaten regulären Ausdruck mit der Bezeichnung "(normalisiert)" an, der dieses Leerzeichen nicht akzeptiert.

Ich habe alle "obs-" Regeln aus dem RFC ignoriert. Dies bedeutet, dass die regulären Ausdrücke nur mit E-Mail-Adressen übereinstimmen, die streng RFC 5322-konform sind. Wenn Sie mit "alten" Adressen übereinstimmen müssen (wie es die lockerere Grammatik einschließlich der "obs-" Regeln tut), können Sie eine der RFC 822-Regexes aus dem vorherigen Absatz verwenden.

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

Beachten Sie, dass einige Quellen (insbesondere w3c ) behaupten, dass RFC 5322 für den lokalen Teil (dh den Teil vor dem @ -Zeichen) zu streng ist. Dies liegt daran, dass "..", "a..b" und "a". sind keine gültigen Punktatome, während sie als Postfachnamen verwendet werden können. Die RFC jedoch nicht erlauben Ortsteilen wie diese, mit der Ausnahme , dass sie zitiert werden müssen. Also statt a..b@example.netdu solltest schreiben "a..b"@example.net, was semantisch äquivalent ist.

Weitere Einschränkungen

SMTP (wie in RFC 5321 definiert ) schränkt den Satz gültiger E-Mail-Adressen (oder tatsächlich: Postfachnamen) weiter ein. Es erscheint vernünftig, diese strengere Grammatik aufzuerlegen, damit die übereinstimmende E-Mail-Adresse tatsächlich zum Senden einer E-Mail verwendet werden kann.

RFC 5321 lässt im Grunde den "lokalen" Teil (dh den Teil vor dem @ -Zeichen) in Ruhe, ist jedoch im Domain-Teil (dh der Teil nach dem @ -Zeichen) strenger. Es erlaubt nur Hostnamen anstelle von Punktatomen und Adressliterale anstelle von Domänenliteralen.

Die in RFC 5321 vorgestellte Grammatik ist zu mild, wenn es sowohl um Hostnamen als auch um IP-Adressen geht. Ich habe mir erlaubt, die fraglichen Regeln zu "korrigieren", indem ich diesen Entwurf und RFC 1034 als Richtlinien verwendet habe. Hier ist der resultierende reguläre Ausdruck.

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

Beachten Sie, dass Sie je nach Anwendungsfall möglicherweise kein "General-Address-Literal" in Ihrer Regex zulassen möchten. Beachten Sie auch, dass ich (?!IPv6:)im endgültigen regulären Ausdruck einen negativen Lookahead verwendet habe , um zu verhindern, dass der Teil "Allgemeines Adressliteral" mit fehlerhaften IPv6-Adressen übereinstimmt. Einige Regex-Prozessoren unterstützen keine negativen Lookaheads. Entfernen Sie die Teilzeichenfolge |(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+aus dem regulären Ausdruck, wenn Sie den gesamten Teil "Allgemeines Adressliteral" entfernen möchten.

Hier ist die Ableitung:

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

Validierung der Benutzereingaben

Ein häufiger Anwendungsfall ist die Validierung von Benutzereingaben, beispielsweise in einem HTML-Formular. In diesem Fall ist es normalerweise sinnvoll, Adressliterale auszuschließen und mindestens zwei Bezeichnungen im Hostnamen zu verlangen. Ausgehend von dem verbesserten RFC 5321-Regex aus dem vorherigen Abschnitt wäre der resultierende Ausdruck:

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

Ich empfehle nicht, den lokalen Teil weiter einzuschränken, z. B. indem Zeichenfolgen in Anführungszeichen ausgeschlossen werden, da wir nicht wissen, welche Art von Postfachnamen einige Hosts zulassen (wie "a..b"@example.netoder sogar "a b"@example.net).

Ich empfehle auch nicht, explizit anhand einer Liste von wörtlichen Domänen der obersten Ebene zu validieren oder sogar Längenbeschränkungen aufzuerlegen (denken Sie daran, wie ".museum" ungültig gemacht wurde [a-z]{2,4}), aber wenn Sie müssen:

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

Stellen Sie sicher, dass Ihre Regex auf dem neuesten Stand ist, wenn Sie sich für eine explizite Domain-Validierung auf oberster Ebene entscheiden.

Weitere Überlegungen

Wenn nur Hostnamen im Domänenteil (nach dem @ -Zeichen) akzeptiert werden, akzeptieren die obigen regulären Ausdrücke nur Beschriftungen mit höchstens 63 Zeichen, wie sie sollten. Sie erzwingen jedoch nicht die Tatsache, dass der gesamte Hostname höchstens 253 Zeichen lang sein darf (einschließlich der Punkte). Obwohl diese Einschränkung streng genommen immer noch regelmäßig ist, ist es nicht möglich, einen regulären Ausdruck zu erstellen, der diese Regel enthält.

Eine weitere Überlegung, insbesondere bei Verwendung der regulären Ausdrücke für die Eingabevalidierung, ist das Feedback an den Benutzer. Wenn ein Benutzer eine falsche Adresse eingibt, wäre es schön, etwas mehr Feedback zu geben als eine einfache "syntaktisch falsche Adresse". Mit "Vanille" -Regexen ist dies nicht möglich.

Diese beiden Überlegungen könnten durch Parsen der Adresse angegangen werden. Die zusätzliche Längenbeschränkung für Hostnamen kann in einigen Fällen auch behoben werden, indem ein zusätzlicher regulärer Ausdruck verwendet wird, der sie überprüft und die Adresse mit beiden Ausdrücken vergleicht.

Keiner der regulären Ausdrücke in dieser Antwort ist für die Leistung optimiert. Wenn die Leistung ein Problem darstellt, sollten Sie prüfen, ob (und wie) der reguläre Ausdruck Ihrer Wahl optimiert werden kann.


3
RFC 6532 aktualisiert 5322 , um vollständige, saubere UTF-8 zu ermöglichen und einzuschließen. Weitere Details hier .

Laut Wikipedia scheint der lokale Teil, wenn er gepunktet ist, eine Beschränkung von 64 Zeichen pro Teil zu haben, und auch der RFC 5322 bezieht sich auf den gepunkteten lokalen Teil, der mit den Einschränkungen der Domänen interpretiert werden soll. Zum Beispiel 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.comsollte nicht validieren. Ich schlage vor, die "+" Zeichen in der ersten Gruppe (Name vor dem optionalen Punkt) und in der zweiten Gruppe (Name nach den folgenden Punkten) in{1,64}
Xavi Montero

Da die Größe der Kommentare begrenzt ist, ist hier der resultierende reguläre Ausdruck, den ich verwenden möchte. Dies ist der am Anfang dieser Antwort stehende. Außerdem wird die Größe im lokalen Teil begrenzt und vor dem "/" ein Schrägstrich hinzugefügt. Symbol wie von PHP und auch in regex101.com gefordert: In PHP verwende ich:$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

VORSICHT: Aus irgendeinem Grund fügt StackOverflow beim Kopieren aus dem gerenderten Markdown versteckte Zeichen hinzu. Kopieren Sie es in regex101.com und Sie werden dort schwarze Punkte sehen. Sie müssen sie entfernen und die Zeichenfolge korrigieren ... Wenn sie in die Antwort integriert sind, können sie möglicherweise korrekt kopiert werden. Entschuldigen Sie die Unannehmlichkeiten. Ich möchte keine neue Antwort hinzufügen, da diese die richtige ist. Außerdem möchte ich nicht direkt bearbeiten, es sei denn, die Community ist der Meinung, dass dies integriert werden sollte.
Xavi Montero

@XaviMontero Danke für den Beitrag von Xavi! Haben Sie einen Verweis auf den RFC, der die Beschränkung auf 64 Zeichen auf lokalen Teilebeschriftungen angibt? Wenn ja, würde ich die Antwort gerne anpassen.
Rinke

73

Es gibt viele Beispiele dafür im Internet (und ich denke sogar eines, das den RFC vollständig validiert - aber es ist zehn / hundert Zeilen lang, wenn Speicher dient). Die Leute neigen dazu, sich davon mitreißen zu lassen, solche Dinge zu bestätigen. Warum nicht einfach überprüfen, ob es ein @ und mindestens eines hat? und erfüllt eine einfache Mindestlänge. Es ist trivial, eine gefälschte E-Mail einzugeben und trotzdem mit einem gültigen regulären Ausdruck übereinzustimmen. Ich würde vermuten, dass falsch positive Ergebnisse besser sind als falsch negative.


1
Ja, aber welcher RFC? :) Dieser [RFC-5322-Validator] ( stackoverflow.com/questions/201323/… ) ist nur etwa vierzig Zeilen lang.
Tchrist

14
EIN . ist nicht nötig. Eine TLD kann E-Mail-Adressen haben, oder es könnte eine IPv6-Adresse geben
Sijmen Mulder

1
RFCs sind nicht das Ende der Geschichte: ICANN erlaubt keine "dotless" Domains mehr: icann.org/news/announcement-2013-08-30-de
Synchro

64

Denken Sie bei der Entscheidung, welche Zeichen zulässig sind, bitte an Ihre apostrophierten und getrennten Freunde. Ich habe keine Kontrolle darüber, dass mein Unternehmen meine E-Mail-Adresse unter Verwendung meines Namens aus dem HR-System generiert. Das schließt den Apostroph in meinem Nachnamen ein. Ich kann Ihnen nicht sagen, wie oft ich von der Interaktion mit einer Website ausgeschlossen wurde, weil meine E-Mail-Adresse "ungültig" ist.


4
Dies ist ein sehr häufiges Problem in Programmen, die ungerechtfertigte Annahmen darüber treffen, was im Namen einer Person erlaubt ist und was nicht. Man sollte keine solchen Annahmen treffen, sondern nur jedes Zeichen akzeptieren, das relevante RFC (s) für erforderlich halten.
Tchrist

4
Ja. Ich bin besonders wütend gegen Programmierer, die Großbuchstaben in E-Mail-Adressen ablehnen! Dumm und / oder faul.
PhiLho

63

Dieser reguläre Ausdruck stammt aus der Email :: Valid- Bibliothek von Perl . Ich glaube, es ist das genaueste, es passt zu allen 822. Und es basiert auf dem regulären Ausdruck im O'Reilly-Buch:

Regulärer Ausdruck, erstellt nach Jeffrey Friedls Beispiel in Mastering Regular Expressions ( 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 Sie müssten auch ein Regex-Meister sein, um zu verstehen, was es tut
Chris McGrath

45

Während Sie in PHP schreiben, würde ich Ihnen raten, die integrierte PHP-Validierung für E-Mails zu verwenden.

filter_var($value, FILTER_VALIDATE_EMAIL)

Wenn Sie eine PHP-Version unter 5.3.6 verwenden, beachten Sie bitte dieses Problem: https://bugs.php.net/bug.php?id=53091

Weitere Informationen zur Funktionsweise dieser integrierten Validierung finden Sie hier: Funktioniert filter_var FILTER_VALIDATE_EMAIL von PHP tatsächlich?


bekommt eine Stimme, genau das, was ich sagen wollte. Behandelt keine IDNs, aber die vorherige Konvertierung in mickrigen Code löst dies. PHP> = 5.3 hat dafür idn_to_ascii (). Eine der besten und einfachsten Möglichkeiten, eine E-Mail zu validieren.
Taylor


42

Ich mache mir nie die Mühe, mit meinem eigenen regulären Ausdruck zu kreieren, denn es besteht die Möglichkeit, dass jemand anderes bereits eine bessere Version entwickelt hat. Ich benutze immer Regexlib , um eine zu finden, die mir gefällt.


1
Dies wurde für Länge und Inhalt markiert, aber es ist immer noch ein guter Beitrag mit 41 Stimmen und sollte nicht gelöscht werden.
Will

37

Es gibt keine, die wirklich brauchbar ist.
Ich diskutiere einige Probleme in meiner Antwort auf Gibt es eine PHP-Bibliothek zur Überprüfung der E-Mail-Adresse? wird es auch in Regexp Erkennung der E-Mail-Adresse schwer diskutiert ?

Kurz gesagt, erwarten Sie nicht, dass ein einziger, verwendbarer regulärer Ausdruck einen ordnungsgemäßen Job macht. Und der beste reguläre Ausdruck überprüft die Syntax, nicht die Gültigkeit einer E-Mail (jhohn@example.com ist korrekt, wird aber wahrscheinlich abprallen ...).


Korrigieren Sie mich, wenn ich falsch liege, aber ich glaube, dass PHP PCRE-Muster verwendet. In diesem Fall sollten Sie in der Lage sein, etwas Ähnliches wie das RFC 5322-Muster von Abigail herzustellen .
Tchrist

@tchrist: Ich bin mir nicht sicher, ob PCRE diese Syntax (die ich entdecke) eingehalten hat. Wenn ja, sind Sie sich nicht sicher, ob PHPs PCRE diese Version von PCRE erreicht hat ... Wenn ich diese Syntax richtig verstehe, können Sie auch einen PEG-Parser verwenden, der viel klarer und vollständiger ist als ein regulärer Ausdruck.
PhiLho

PCRE hat es eingeholt, aber vielleicht hat PHP PCRE nicht eingeholt. ☹
tchrist

36

Ein einfacher regulärer Ausdruck, der zumindest keine gültige E-Mail-Adresse ablehnt, ist die Suche nach etwas, gefolgt von einem @ -Zeichen und etwas gefolgt von einem Punkt und mindestens zwei Dingen. Es wird nichts abgelehnt, aber nachdem ich die Spezifikation überprüft habe, kann ich keine E-Mail finden, die gültig und abgelehnt wäre.

email = ~ /.+@[^@]+\.[^@]{2,}$/


3
Das habe ich gesucht. Nicht sehr restriktiv, stellt jedoch sicher, dass nur 1 @ vorhanden ist (da wir eine Liste analysieren und sicherstellen möchten, dass keine Kommas fehlen). Zu Ihrer Information, Sie können ein @ auf der linken Seite haben, wenn es in Anführungszeichen steht: Valid_email_addresses , aber es ist ziemlich Rand.
Josh

2
Nachdem ich es benutzt hatte, stellte ich fest, dass es nicht genau funktionierte. /^[^@]+@[^@]+\.[^@]{2}[^@]*$/ prüft tatsächlich auf 1 @ Zeichen. Ihre Regex lässt aufgrund des. * Am Ende mehrere durch.
Josh

1
Recht. Ich versuche nicht, alle ungültigen E-Mails abzulehnen. Verhindern Sie einfach, eine gültige E-Mail-Adresse abzulehnen.
Spig

1
Es wäre weitaus besser, dies zu verwenden: /^[^@]+@[^@]+\.[^@]{2,4}$/Stellen Sie sicher, dass es mit 2 bis 4 Nicht-@ -Zeichen endet. Wie @Josh betonte, erlaubt es jetzt am Ende ein zusätzliches @. Sie können dies aber auch ändern in: /^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/Da alle Domänen der obersten Ebene aZ-Zeichen sind. Sie können die 4durch 5oder mehr ersetzen, sodass Domain-Namen der obersten Ebene auch in Zukunft länger sein können.
FLIEG

@FLY, ka @ foo. gibt korrekt zurück. Soll es nach den Maßstäben sein?
SexyBeast

29

Sie können das vom jQuery Validation-Plugin verwendete verwenden:

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

das scheint einen guten Job zu machen. Es erlaubte: a-b'c_d.e@f-g.haber war in der Lage, die unangemessenen Variationen zu fangen, wie a-b'c_d.@f-g.hunda-b'c_d.e@f-.h
dsdsdsdsd

25

Die umfassendste Bewertung des besten regulären Ausdrucks zur Validierung einer E-Mail-Adresse finden Sie unter diesem Link. " Vergleichen der E-Mail-Adresse zur Überprüfung regulärer Ausdrücke "

Hier ist der aktuelle Top-Ausdruck zu Referenzzwecken:

/^([\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: Dieser Link ist nicht wirklich korrekt. Die Aussage, dass es kein perfektes Muster für die Validierung von E-Mail-Adressen geben kann, ist offensichtlich fehlerhaft. Sie können , aber Sie müssen sicherstellen, dass Sie dem RFC bis zum Buchstaben folgen. Und Sie müssen auch den richtigen RFC auswählen.
Tchrist

Das "Beste" funktioniert derzeit nicht mit Java Regex - selbst nachdem der String ordnungsgemäß maskiert und konvertiert wurde.
Eric Chen

23

Ganz zu schweigen davon, dass nicht-lateinische (chinesische, arabische, griechische, hebräische, kyrillische usw.) Domainnamen in naher Zukunft zugelassen werden sollen . Jeder hat das E - Mail - Regex verwendet zu ändern, da diese Zeichen sind sicherlich nicht abgedeckt werden [a-z]/inoch \w. Sie werden alle scheitern.

Der beste Weg, um die E-Mail-Adresse zu validieren, besteht darin , eine E-Mail an die betreffende Adresse zu senden, um die Adresse zu validieren. Wenn die E-Mail-Adresse Teil der Benutzerauthentifizierung ist (Registrieren / Anmelden / usw.), können Sie sie perfekt mit dem Benutzeraktivierungssystem kombinieren. Dh senden Sie eine E-Mail mit einem Link mit einem eindeutigen Aktivierungsschlüssel an die angegebene E-Mail-Adresse und erlauben Sie die Anmeldung nur, wenn der Benutzer das neu erstellte Konto über den Link in der E-Mail aktiviert hat.

Wenn der Zweck des regulären Ausdrucks nur darin besteht, den Benutzer in der Benutzeroberfläche schnell darüber zu informieren, dass die angegebene E-Mail-Adresse nicht im richtigen Format aussieht, sollten Sie am besten überprüfen, ob sie im Wesentlichen dem folgenden regulären Ausdruck entspricht:

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

So einfach ist das. Warum um alles in der Welt interessieren Sie sich für die Zeichen, die im Namen und in der Domäne verwendet werden? Es liegt in der Verantwortung des Kunden, eine gültige E-Mail-Adresse einzugeben, nicht die des Servers. Selbst wenn der Client eine syntaktisch gültige E-Mail-Adresse wie eingibt aa@bb.cc, garantiert dies nicht, dass es sich um eine legitime E-Mail-Adresse handelt. Niemand Regex kann das abdecken.


4
Ich bin damit einverstanden, dass das Senden einer Authentifizierungsnachricht normalerweise der beste Weg für diese Art von Dingen ist. Syntaktisch korrekt und gültig sind nicht dasselbe. Ich bin frustriert, wenn ich meine E-Mail-Adresse zweimal für "Bestätigung" eingeben muss, als ob ich nicht sehen kann, was ich eingegeben habe. Ich kopiere sowieso nur das erste auf das zweite, es scheint immer mehr benutzt zu werden.
PeteT

zustimmen! aber diese Regex denke ich nicht ist gültig, weil es spacesnach dem @.zB erlaubt . test@test.ca com netBetrachten Sie eine gültige E-Mail unter Verwendung des obigen regulären Ausdrucks, wenn sie ungültig zurückgegeben werden soll.
CB4

20

Die HTML5-Spezifikation schlägt einen einfachen regulären Ausdruck für die Überprüfung von E-Mail-Adressen vor:

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

Dies entspricht absichtlich nicht RFC 5322 .

Hinweis: Diese Anforderung stellt eine vorsätzliche Verletzung von RFC 5322 dar , das eine Syntax für E-Mail-Adressen definiert, die gleichzeitig zu streng (vor dem @Zeichen), zu vage (nach dem @Zeichen) und zu lasch (Kommentare, Leerzeichen zulassen) ist. und zitierte Zeichenfolgen auf eine Weise, die den meisten Benutzern unbekannt ist), um hier von praktischem Nutzen zu sein.

Die Gesamtlänge könnte auch auf 254 Zeichen pro RFC 3696-Errata 1690 begrenzt werden .


Beste Antwort! Hier ist ein Link zur w3-Empfehlung: w3.org/TR/html5/forms.html#valid-e-mail-address Dieser reguläre Ausdruck wird von vielen Browsern übernommen.
Ryan Taylor

3
Dies ist also nicht die beste Antwort! Dieses Muster entspricht dieser vollständig ungültigen Adresse : invalid@emailaddress. Ich würde Vorsicht und viele Tests empfehlen, bevor Sie es verwenden!
Sheridan

@ Sheridan, wenn Sie denken, dass es ein Problem mit der HTML5-Spezifikation gibt, können Sie ein Problem hier ansprechen
Luna

Dies fügt nicht viel über stackoverflow.com/a/8829363 hinzu und wäre meiner Meinung nach besser als eine Bearbeitung oder ein Kommentar dazu.

Beispiel @ localhost ist gültig, aber für eine reale Anwendung, die Sie möglicherweise eine Domänenerweiterung erzwingen möchten, müssen Sie lediglich das letzte * in ein + ändern, um dies zu erreichen (indem Sie diesen Teil des Musters von 0+ auf 1+ ändern )
Mitch Satchwell

15

Für eine anschauliche Demonstration ist das folgende Monster ziemlich gut, erkennt jedoch immer noch nicht alle syntaktisch gültigen E-Mail-Adressen korrekt: Es erkennt verschachtelte Kommentare mit einer Tiefe von bis zu vier Ebenen.

Dies ist ein Job für einen Parser, aber selbst wenn eine Adresse syntaktisch gültig ist, kann sie möglicherweise nicht geliefert werden. Manchmal muss man auf die Hinterwäldler-Methode zurückgreifen: "Hey, ihr alle, schaut uns zu!"

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

Gemäß dem offiziellen Standard RFC 2822 ist eine gültige E-Mail-Regex gültig

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

Wenn Sie es in Java verwenden möchten, ist es wirklich sehr einfach

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
Ihre Regex enthält keinen ersten Großbuchstaben, z. B. Leonardo.davinci@gmail.com, was für einige Benutzer ärgerlich sein könnte. Verwenden Sie stattdessen dieses:(?:[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 Danke, bitte bearbeiten Sie die Antwort, ich werde die Änderung akzeptieren.
AZ_

Wenn ich diese Änderung zu Ihrer Antwort hinzufüge, wird es nicht mehr RFC 2822 sein, also weiß ich nicht, ob das richtig ist.
Kebab Krabby

11

Hier ist das PHP, das ich benutze. Ich habe diese Lösung im Sinne von "False Positives sind besser als False Negatives" gewählt, wie von einem anderen Kommentator hier erklärt, UND im Hinblick darauf, Ihre Antwortzeit hoch und die Serverlast niedrig zu halten ... es besteht wirklich keine Notwendigkeit, Serverressourcen damit zu verschwenden Ein regulärer Ausdruck, wenn dadurch der einfachste Benutzerfehler beseitigt wird. Sie können dies jederzeit verfolgen, indem Sie eine Test-E-Mail senden, wenn Sie möchten.

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

1
a) Die "Abfall-Server-Ressourcen" sind infinitesimal, aber wenn Sie so geneigt sind, können Sie dies clientseitig mit JS tun. b) Was benötigen Sie, um eine Registrierungs-Mail zu senden, und der Benutzer gibt mich @ lostthedotcom ein? Ihre "Lösung" schlägt fehl und Sie verlieren einen Benutzer.
Johnjohn

a) Sich auf eine JS-Validierung zu verlassen, die fehlschlagen würde, wenn JavaScript deaktiviert ist, klingt auch nicht nach der besten Idee (nur übrigens)
auco

11

RFC 5322 Standard:

Ermöglicht den lokalen Teil des Punktatoms, den lokalen Teil der angegebenen Zeichenfolge, den veralteten lokalen Teil (gemischte Punktatome und die Zeichenfolge der angegebenen Zeichenfolge), die Domänennamendomäne (die IPv4-, IPv6- und IPv4-zugeordnete IPv6-Adresse) und die Domänenliteraldomäne. und (verschachtelte) 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:

Ermöglicht die lokale Literaldomäne "Dot-Atom Local-Part", "Quoted-String Local-Part", "Domain Name Domain" und (IPv4-, IPv6- und IPv4-zugeordnete IPv6-Adresse) Domain.

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

Basic:

Ermöglicht Punkt-Atom-Domänen für lokale Teile und Domänennamen (erfordert mindestens zwei Domänennamenbezeichnungen, wobei die TLD auf 2-6 alphabetische Zeichen beschränkt ist).

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

In was für einer Teufelssprache ist das? Ich sehe eine /DFlagge, und Sie haben sie mit einfachen Anführungszeichen zitiert, aber auch Schrägstriche verwendet, um das Muster abzugrenzen? Es ist nicht Perl und es kann nicht PCRE sein. Ist es also PHP? Ich glaube, das sind die einzigen drei, die eine Rekursion zulassen (?1).
Tchrist

Es ist in PHP, das PCRE verwendet. Die Schrägstriche werden nur verwendet, um Sonderzeichen wie Klammern, eckige Klammern und natürlich Schrägstriche und einfache Anführungszeichen abzugrenzen. Das / D-Flag soll, wenn Sie es nicht wussten, verhindern, dass am Ende der Zeichenfolge eine neue Zeile hinzugefügt wird, was sonst zulässig wäre.
Michael

9

Seltsam, dass Sie TLDs mit 4 Zeichen nicht zulassen können. Sie verbieten Personen die Verwendung von .info und .name , und die Längenbeschränkung stoppt .travel und .museum , aber ja, sie sind weniger verbreitet als TLDs mit 2 Zeichen und TLDs mit 3 Zeichen.

Sie sollten auch Alphabete in Großbuchstaben zulassen. E-Mail-Systeme normalisieren den lokalen Teil und den Domain-Teil.

Für Ihre Regex des Domain-Teils kann der Domain-Name nicht mit '-' beginnen und nicht mit '-' enden. Dash kann nur dazwischen bleiben.

Wenn Sie die PEAR-Bibliothek verwendet haben, überprüfen Sie deren E-Mail-Funktion (vergessen Sie den genauen Namen / die Bibliothek). Sie können die E-Mail-Adresse überprüfen, indem Sie eine Funktion aufrufen. Die E-Mail-Adresse wird gemäß der Definition in RFC822 überprüft.


2
@ Joseph Yee: Ist RFC 822 nicht etwas veraltet?
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;
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.