Email überprüfen mit preg_match
Klaus
- php
0 Michi3 Sven Rautenberg
Ich über prüfe meine Emaileingabe auf valität, doch jetzt habe ich ein kleines Problem, ich bekomme einen fehler wenn die Email test.test@example.com heisst.
Wo habeich den da den Fehler?
if (preg_match('/[1][a-zA-Z0-9_-]+([.][a-zA-Z0-9._-]+)*[@][a-zA-Z0-9_-]+([.][a-zA-Z0-9_-]+)*[.][a-zA-Z]{2,4}$/', $mail))
^0-9 ↩︎
if (preg_match( '/^([a-z0-9]+([-_.]?[a-z0-9])+)@[a-z0-9äöü]+([-_.]?[a-z0-9äöü])+.[a-z]{2,4}$/i', $amail))
so geht es mit Punkt und mit deutschen Sonderzeichen
Moin!
if (preg_match( '/^([a-z0-9]+([-_.]?[a-z0-9])+)@[a-z0-9äöü]+([-_.]?[a-z0-9äöü])+.[a-z]{2,4}$/i', $amail))
so geht es mit Punkt und mit deutschen Sonderzeichen
Dein Regex ist mindestens genauso kaputt, wie der von Klaus.
Umlaute in Domainnamen, die als Mailziel verwendet werden, sind nackt nicht zulässig, sondern müssen mit Punycode-Regeln in ASCII-Domains gewandelt werden. Weil das bislang die Mailclients nicht flächendeckend tun, da es keinerlei Standardisierungs-Vereinbarung dafür gibt, sind Umlautdomains im Mailverkehr unbenutzbar.
Die fehlerhafte Einschränkung der TLD-Länge ist bei dir ebenso vertreten, wie die fehlerhafte Einschränkung des User-Anteils der Adresse. Gerade der Useranteil ist praktisch keinerlei Regeln unterworfen, deshalb ist es sinnlos, an dieser Stelle irgendetwas strenger zu prüfen.
- Sven Rautenberg
Moin!
Ich über prüfe meine Emaileingabe auf valität, doch jetzt habe ich ein kleines Problem, ich bekomme einen fehler wenn die Email test.test@example.com heisst.
Wo habeich den da den Fehler?
Im Regex insgesamt.
Deine Forderungen laut Regex:
1. Mailadresse darf nicht mit Ziffern beginnen - das ist Unsinn. An der Stelle des ersten Zeichens dürfen sehr wohl 0-9 auftreten - allerdings akzeptierst du hier jedes andere mögliche Zeichen, und das ist dann doch eher unsinnig.
2. Als weitere Zeichen kommen dann mindestens eines aus "a-zA-Z0-9_-". Damit hätte der Useranteil schon eine Mindestlänge von zwei Zeichen, was ebenfalls unsinnig ist.
3. Danach kommt eventuell ein Punkt unnd weitere Zeichen obiger Klassifizierung, allerdings jetzt mit Punkt drin. Das ganze Null bis unendlich oft. Naja, unendlich lange Mailadressen gibts nicht, aber dass vor dem ersten Punkt in der Mailadresse mindestens zwei Zeichen kommen müssen, und nach dem Punkt mindestens eines, ist auch falsch. Der Punkt ist ein ganz normales Zeichen in Mailadressen.
4. Ein @ muss vorkommen. Das ist ok. Warum es als Zeichenklasse notiert ist, erschließt sich allerdings nicht, die eckigen Klammern sind überflüssig.
5. Im Domainteil geht es lustig weiter. Beispielsweise ist der Unterstrich als Zeichen erlaubt - der ist nun aber in Domains gerade verboten, zumindest in denen, die im DNS-System stehen. Ich hatte mal einen Admin, der hat Unterstrich-Domains in der lokalen Hosts-Datei definiert und das erst rückgängig gemacht, als ich ihm berichten musste, dass meine Software diese Domain nicht akzeptiert, weil die eben dns-gültige Namen validiert.
6. Wie gehts weiter in der Domain: Nach mindestens einem Zeichen kommt etwas, was mit Punkt beginnt und danach auch mindestens ein Zeichen enthält. Soweit OK (bis auf den Unterstrich).
7. Danach dann noch mal ein Punkt sowie zwei bis vier Zeichen a-zA-Z - das ist wiederum falsch, denn als Top-Level-Domain gibt es ebenfalls keinerlei Begrenzung - wenn man die Nachrichten verfolgt, werden gerade beliebig viele neue Domainnamen ausgedacht und registriert, und ".museum" ist schon lange existent. Es gibt eine Längenbeschränkung für Domainnamen: Jedes Einzelteil darf nicht länger als 63 Zeichen sein, es darf nicht mehr als 127 Einzelteile geben, und insgesamt darf die Domain nicht länger als 255 Zeichen sein. Das gilt auch für die Top-Level-Domain.
if (preg_match('/[1][a-zA-Z0-9_-]+([.][a-zA-Z0-9._-]+)*[@][a-zA-Z0-9_-]+([.][a-zA-Z0-9_-]+)*[.][a-zA-Z]{2,4}$/', $mail))
Insofern ist das Mailvalidieren mit regulärem Ausdruck relativ sinnlos. Einerseits beweist es nicht, dass die Mailadresse existiert und bemailt werden darf, andererseits entscheidet der Mailserver, den man benutzen möchte, über die Korrektheit einer Adresse und würde sich im Zweifel melden.
Mein Ansatz für die Validierung von Mailadressen war bislang immer: preg_match("/^.+@.+\..+$/", $mail)
- das ist simpel genug, dass man es nicht kaputtkriegen kann. Mindestens ein Zeichen vor dem @, mindestens ein Punkt hinter dem @, getrennt durch Zeichen.
PHP bietet allerdings auch noch eine Alternative: filter_var().
Das Beispiel auf der Seite zeigt praktischerweise das Vorgehen für Mailadressen, in zwei Varianten:
<?php
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
?>
- Sven Rautenberg
^0-9 ↩︎
Tach!
Mein Ansatz für die Validierung von Mailadressen war bislang immer:
preg_match("/^.+@.+\..+$/", $mail)
- das ist simpel genug, dass man es nicht kaputtkriegen kann. Mindestens ein Zeichen vor dem @, mindestens ein Punkt hinter dem @, getrennt durch Zeichen.
Warum muss da mindestens ein Punkt im Domain-Teil stehen? Wie du schon sagtest, wird mit einer syntaktisch gültigen Adresse nichts weiter ausgesagt. Ich aber ärgere mich immer, wenn ich mal eine Software testen will und root@localhost erfolglos einzugeben versuche. Neulich bestand ein System gar darauf, eine offizielle TLD vorgesetzt zu bekommen, also auch irgendwas@irgendwas.local war nicht eingebbar, obwohl eine an diese Adresse gesendete Mail ihr von mir gewünschtes Ziel problemlos erreicht hätte. Stattdessen musste ich die Mail an einen Account im Internet senden lassen. So ein Unfug.
Ich gebe auch gern mal an völlig unwichtigen Mail-Adressen verlangenden Stellen ...@example.com an. Das schlucken die meisten System, ohne dass es irgendwem nutzt. Sämtliche Prüfverfahren, die nicht die tatsächliche Zustellbarkeit der Mail prüfen, halte ich daher für sinnlos bis kontraproduktiv.
dedlfix.
Sämtliche Prüfverfahren, die nicht die tatsächliche Zustellbarkeit der Mail prüfen
Gibt es sowas denn?
Gerd
Sämtliche Prüfverfahren, die nicht die tatsächliche Zustellbarkeit der Mail prüfen
Gibt es sowas denn?
Ja, siehe Opt-in unter "Double-Opt-in".
Gruß Gunther
- [...] eine Mindestlänge von zwei Zeichen, was ebenfalls unsinnig ist.
Eine Mindestlänge von 1 Zeichen ist übrigens ebenfalls nicht ganz richtig - der local-part darf sogar ein Leerstring sein, dafür muss er allerdings ein Begrenzer einschlossen werden werden ""@example.com - wobei das de facto natürlich dann 2 Zeichen im local-part sind :)
- [...] Der Punkt ist ein ganz normales Zeichen in Mailadressen.
Wobei ein Punkt nicht am Anfang oder Ende des local-part vorkommen darf - ebenso sind wiederholungen des Punkts nicht erlaubt - als z.B. foo..bar@example.com geht nicht ".foo"@example.com ist aber möglich, da hier der ungültige Punkt entsprechend maskiert (mit Begrenzern) ist.
- Danach dann noch mal ein Punkt sowie zwei bis vier Zeichen a-zA-Z - das ist wiederum falsch, denn als Top-Level-Domain gibt es ebenfalls keinerlei Begrenzung - wenn man die Nachrichten verfolgt, werden gerade beliebig viele neue Domainnamen ausgedacht und registriert, und ".museum" ist schon lange existent. Es gibt eine Längenbeschränkung für Domainnamen: Jedes Einzelteil darf nicht länger als 63 Zeichen sein, es darf nicht mehr als 127 Einzelteile geben, und insgesamt darf die Domain nicht länger als 255 Zeichen sein. Das gilt auch für die Top-Level-Domain.
Dann würden aber immer noch IPv4 und IPv6-Adressen fehlen, da ist nicht nur Einzelteile gibt, die länger als 4 Zeichen sind, sondern eben auch welche mit nur 1 Zeichen (genauer gesagt einer Dezimalziffer) - und natürlich Doppelpunkte bei IPv6-Adressen (inklusive der eckigen Klammern als Bbegrenzer) also z.B. foo@[::1/128]
Insofern ist das Mailvalidieren mit regulärem Ausdruck relativ sinnlos.
Zumindest per Hand mit einem selbstgestrickten Ausdruck, den kann man nicht schnell zusammenzimmern.
Mein Ansatz für die Validierung von Mailadressen war bislang immer:
preg_match("/^.+@.+\..+$/", $mail)
- das ist simpel genug, dass man es nicht kaputtkriegen kann. Mindestens ein Zeichen vor dem @, mindestens ein Punkt hinter dem @, getrennt durch Zeichen.
Das ist imho zu wenig, da sie Syntaxfehler nicht ausschließt, die gerne mal eingebaut werden - z.B. Leute die mehrere Mail-Adressen aneinanderhängen (kommt hier oft genug vor).
PHP bietet allerdings auch noch eine Alternative: filter_var().
Und falls es damit nicht klappt, weil filter_var() aus irgend einem Grund nicht zur verfügung steht, kann man den PCRE auch direkt aus dem Sourcecode von PHP graben, den PHP für FILTER_VALIDATE_EMAIL verwendet:
/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){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}))\]))$/iD
Eine Mindestlänge von 1 Zeichen ist übrigens ebenfalls nicht ganz richtig - der local-part darf sogar ein Leerstring sein, dafür muss er allerdings ein Begrenzer einschlossen werden werden ""@example.com - wobei das de facto natürlich dann 2 Zeichen im local-part sind :)
Nachtrag: das war so gemeint, dass der local-part darf natürlich nicht "leer" sein, aufgrund der Schwammigkeit in der Syntaxprüfung kann man hier aber problemlos einen Leerstring reinschmuggeln (sofern damit überhaupt irgend ein Mailserver Postfächer mit einem Leerstring als Namen erlaubt).
[latex]Mae govannen![/latex]
Mein Ansatz für die Validierung von Mailadressen war bislang immer:
preg_match("/^.+@.+\..+$/", $mail)
- das ist simpel genug, dass man es nicht kaputtkriegen kann. Mindestens ein Zeichen vor dem @, mindestens ein Punkt hinter dem @, getrennt durch Zeichen.Das ist imho zu wenig, da sie Syntaxfehler nicht ausschließt, die gerne mal eingebaut werden - z.B. Leute die mehrere Mail-Adressen aneinanderhängen (kommt hier oft genug vor).
Ich prüfe nur noch folgendes:
Dadurch lasse ich zwar viele illegale Kombinationen durch, das ist mir aber i.d.R. lieber als eine gültige Adresse zu blockieren. Die Prüfung kann ich mit einfachen String-Methoden erreichen, ohne RegEx.
PHP bietet allerdings auch noch eine Alternative: filter_var().
Dabei muß man sich dann wieder darauf verlassen, daß beim Programmieren bzw. erstellen der RegEx kein Fehler gemacht wurde, der eigentlich gültige Adressen ausschließt, weil sowas…
/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){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}))\]))$/iD
wartungstechnisch reichlich undurchschaubar ist.
Stur lächeln und winken, Männer!
Kai
Dabei muß man sich dann wieder darauf verlassen, daß beim Programmieren bzw. erstellen der RegEx kein Fehler gemacht wurde, [...]
Das ist eine Abwägungssache - hast du mehr false positives, weil der Ausdruck fehlerhaft ist oder mehr Fehleingaben und dadurch unnütze Daten, weil die Benutzer fehlerhafte Adressen eingeben?
Wir haben das bei eine größeren Tourismusseite ein paar Monate mitprotokolliert: sprich die Formularvalidierung hat alle als ungültig bemängelten Adressen einfach in ein Logfile geschrieben. Es war keine einzige dabei, die unberechtigerweis abgelehnt wurde - wäre die Prüfung hingegen "einfacher" gewesen wären, hätten viele der Anfragen aufgrund einer ungültigen Mailadresse nicht bearbeitet werden können - und da geht in manchen Branchen viel Geld flöten.