2010-12-01 3 views
8

Wir alle wissen, dass ein Regex, um E-Mails richtig zu validieren, wäre quite complicated. Allerdings hat jQuery Validierung Plugin eine kürzere regex (beigetragen von Scott Gonzalez), Spanning nur ein paar Zeilen:Warum ist jQuery E-Mail-Validierung Regex so einfach?

/^((([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])))\.?$/ 

Warum ist das so ‚einfach‘ im Vergleich zu den bekannteren Ungeheuerlichkeit? Gibt es Fälle, in denen eine Regex fehlschlägt und die andere erfolgreich wäre (ob es sich um gültige oder ungültige E-Mails handelt)?

+12

Einfach ist nicht das Wort, das ich für diese Regex verwenden würde;) – JaredPar

+4

* Ahem * Simple? Wenn diese Regex einfach ist, was würden Sie als kompliziert einstufen? – Alex

+0

Sprechen über das Treten in der schreibgeschützten Sprache Gebiet ... – Serguei

Antwort

10

Die Regex ist eine individuelle Kombination aus:

  • RFC 2234 ABNF
  • RFC 2396 URI Generic Syntax (obseleted von RFC 3986)
  • RFC 2616 Hypertext Transfer Protocol - HTTP/1.1
  • RFC 2822 Internet Message Format
  • RFC 3987 IRI
  • RFC 3986 URI Generic Syntax

Ich schrieb die Regex, wenn entworfen wurde und RFC 5322 nicht existierte. Wenn Sie sich die Reihenfolge ansehen, in der die RFCs geschrieben wurden, werden Sie bemerken, dass die Definition für IRI und URI geändert wurde, nachdem das Internet Message Format geschrieben wurde. Dies bedeutet, dass RFC 2822 keine aktuellen IRI-Definitionen unterstützt. Leider war es keine einfache Aufgabe, Definitionen einfach zu ersetzen, also musste ich auswählen, welche Definitionen aus welchen RFCs zu verwenden sind. Ich habe auch Entscheidungen getroffen, was zu entfernen ist (wie Unterstützung für Kommentare).

Die Regex ist nicht vollständig handgeschrieben. Während ich jeden Abschnitt der Regex manuell schrieb, schrieb ich den "Kleber". Jede Definition aus den RFCs wird in einer Variablen gespeichert, wobei zusammengesetzte Definitionen die Variablen verwenden, die die einfacheren Definitionen speichern (@Walf: deshalb gibt es so viele Untermuster und -Ordner).

Um die Angelegenheit zu komplizieren, wird die Version der Regex, die im jQuery Validation-Plugin verwendet wird, noch weiter modifiziert, um Unterschiede zwischen spezifizierten Adressen und Benutzererwartungen einer gültigen Adresse zu berücksichtigen. Ich habe keine Erinnerung daran, welche Änderungen ich vorgenommen habe. Ich habe Jörn Zaefferer (dem Autor des Validierungs-Plugins) versprochen, dass ich ein neueres Skript schreiben würde, um die Regex zu generieren. Mit dem neuen Skript können Sie Optionen für das festlegen, was Sie tun und nicht unterstützen möchten (erforderliche TLD, spezifische TLDs, IPv6, Kommentare, veraltete Definitionen, zitierte lokale Namen usw.). Das war vor 5 Jahren. Ich habe es einmal angefangen, aber nie beendet. Vielleicht werde ich es eines Tages tun. Was ich bisher auf GitHub: https://github.com/scottgonzalez/regex-builder

Wenn Sie für die Validierung von E-Mail-Adressen eine Regex wollen, würde ich die folgende regex vorschlagen, die in der HTML5 specification enthalten ist:

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-][email protected][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])?)*$/

Wenn Sie Verwenden Sie Regex-Builder und deaktivieren Sie alle Optionen, Sie werden etwas Ähnliches bekommen. Aber es ist ungefähr ein Jahr her, dass ich mir das anschaue, also erinnere ich mich nicht, was die Unterschiede sind.


Ich würde auch ausdrücklich erwähnt RFC 822. der Link in der ursprünglichen Frage darauf hin, dass es zwar toll, dass RFC 822 uns von Arpanet zum ARPA Internet fortgeschritten ist dies nicht genau Strom. Das Internet hat in den letzten drei Jahrzehnten einige Fortschritte gemacht und dieses RFC wurde zweimal ersetzt. Ich würde gerne neue Arbeiten nach den neuesten Standards sehen.


UPDATE:

Ein Freund fragte mich, warum die HTML5 regex nicht UTF-8 unterstützt. Ich habe Hixie nie danach gefragt, aber ich nehme an, dass dies der Grund ist: Obwohl einige TLDs IDNs (International Domain Names) im Jahr 2000 zu unterstützen begannen und RFC 3987 (IRI) im Jahr 2005 geschrieben wurde, als RFC 5322 im Jahr 2008 geschrieben wurde Es wurden nur Zeichen in den Bereichen 33-90 und 94-126 als gültiger Text aufgelistet (Zeichen, die in einem Domänenliteral zulässig sind). HTML5 basiert auf RFC 5322 und daher gibt es keine UTF-8-Unterstützung. Es ist sicherlich seltsam, dass RFC 5322 IDNs nicht berücksichtigt, aber es ist nichts wert, dass selbst IDNs 2008 nicht wirklich verwendbar waren. Erst im Jahr 2010 genehmigte ICANN den ersten Satz von IDNs. Aber selbst heute, wenn Sie ein IDN verwenden möchten, müssen Sie Ihren Domain-Namen mit Punycode zerstören, wenn Sie wirklich wollen, dass E-Mail und DNS global funktionieren.

UPDATE 2:

Aktualisiert HTML5 regex die aktualisierte Spezifikation entsprechen, die von 255 Zeichen 63 Zeichen Etikettenlänge Grenzen geändert, wie in RFC 1034 section 3.5 angegeben.

+0

Die HTML5-Spezifikationsseite hat eine etwas andere Version als dieses Muster; vielleicht wurde es aktualisiert? Hauptsächlich beschränkt es die Abschnitte auf 63 (in den RFCs als Labels bezeichnet). Es verhindert auch, dass ein Label mit einem Bindestrich endet. – goodeye

+0

Da Stack und Wikipedia sich gegenseitig referenzieren, habe ich hier einige gute Zusammenfassungen gefunden: http://blog.sacaluta.com/2011/12/dns-domain-names-253-or-255-bytesoctets.html und http://blogs.msdn.com/b/oldnewthing/archive/2012/04/12/10292868.aspx – goodeye

+0

@goodeye Danke für das Hinzeigen. Ich habe die Regex aktualisiert, obwohl es für Etikettenendungen keine Änderung gab, nur die Länge. –

1

Das sieht nicht richtig aus: Was ist mit dem Unicode? Welcher RFC validiert dies?

Siehe this answer für eine ordnungsgemäße RFC5322-Validierung Regex.

+0

Es sieht auch nicht richtig zu mir; daher die Frage. Dies wird direkt aus einer Datei mit der Bezeichnung '$ Id: jquery.validate.js 6403 2009-06-17 14: 27: 16Z joern.zaefferer $' Zeile 1011 übernommen. – configurator