"perfekte" Validierung von E-Mail-Adressen, IP-Adressen usw
suit
- php
Tach,
ich habe grade zur E-Mail-Adressvaldierung (zumindest syntaktisch) die Funktion filter_var() entdeckt (funktioniert ab PHP 5.2).
if (!(filter_var('random@example.com', FILTER_VALIDATE_EMAIL))) {
echo 'E-Mail-Adresse ist falsch';
}
Im Vergleich zu den sonst hier geposteten RegEx-Monstern ist das mal eine wirklich einfache Lösung. Leider finde ich auf php.net keine Liste mit Beschreibung aller möglichen Filter - lediglich filter_list() soll eine Auflistung der verfügbaren Filter liefern.
Ich würde gerne wissen, ob die Funktion nur die Gültigkeit der Mail-Adresse gemäß RFC 2821/2822 prüft oder aber auch beachtet, dass es Einschränkungen durch das SMTP gibt.
Im Artikel Validierung von eMail-Adressen steht zu dieser Funktion übrigens nichts (eh klar, Artikel zu alt).
Ggf. benötigt den Spaß der ein oder andere - die Frage taucht ja immer mal wieder hier im Forum auf, eine zufriedenstellende Antwort gibts aber meistens nicht - es wird halt immer gerne gestritten, welcher reguläre Ausdruck nun der am wenigsten fehlerhafte ist :).
Hi!
ich habe grade zur E-Mail-Adressvaldierung (zumindest syntaktisch) die Funktion filter_var() entdeckt (funktioniert ab PHP 5.2).
Im Vergleich zu den sonst hier geposteten RegEx-Monstern ist das mal eine wirklich einfache Lösung.
Das RegEx-Monster versteckt sich stattdessen in dieser Funktion selbst.
Leider finde ich auf php.net keine Liste mit Beschreibung aller möglichen Filter -
Im Kapitel Filter, in dem auch die oben genannte Funktion beschrieben ist, gibt es diese Liste: Types of filters.
Ich würde gerne wissen, ob die Funktion nur die Gültigkeit der Mail-Adresse gemäß RFC 2821/2822 prüft oder aber auch beachtet, dass es Einschränkungen durch das SMTP gibt.
Welche Einschränkungen? Meinst du, ob die Funktion den betreffenden Mail-Server kontaktiert und dort nach der Adresse fragt? Wenn ja, so lautet die Antwort nein. Das würde auch unter Umständen viel zu lange dauern. Deswegen wäre eine derartige generelle und nicht abschaltbare Prüfung ein Kriterium, das die Funktion in vielen fällen unbrauchbar machte.
Lo!
Das RegEx-Monster versteckt sich stattdessen in dieser Funktion selbst.
Firma dankt - auch ohne entsprechende PHP-Version lässt sich das dann nutzen.
preg_match("/^((\\\"[^\\\"\\f\\n\\r\\t\\b]+\\\")|([A-Za-z0-9_][A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\`\\|\\{\\}]*(\\.[A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\`\\|\\{\\}]*)*))@((\\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9])(([A-Za-z0-9\\-])*([A-Za-z0-9]))?(\\.(?=[A-Za-z0-9\\-]))?)+[A-Za-z]+))$/D",
$e_mail_adresse);
Welche Einschränkungen?
Ich meinte die Längenbeschränkung. Die Antwort ist, PHP ignoriert sie - genauso wie E-Mail-Adressen mit IDN im domain-part. Ansonsten scheint der Ausdruck super zu funktionieren.
RFC 5321: 4.5.3.1. Size Limits and Minimums
[...]
4.5.3.1.1. Local-part
The maximum total length of a user name or other local-part is 64
octets.
4.5.3.1.2. Domain
The maximum total length of a domain name or number is 255 octets.
4.5.3.1.3. Path
The maximum total length of a reverse-path or forward-path is 256
octets (including the punctuation and element separators).
Hello,
Firma dankt - auch ohne entsprechende PHP-Version lässt sich das dann nutzen.
preg_match("/^((\"[^\"\f\n\r\t\b]+\")|([A-Za-z0-9_][A-Za-z0-9_\!\#\$\%\&\'\\+\-\~\/\^\\\|\\{\\}]*(\\.[A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\
\|\{\}])))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9])(([A-Za-z0-9\-])([A-Za-z0-9]))?(\.(?=[A-Za-z0-9\-]))?)+[A-Za-z]+))$/D",
$e_mail_adresse);
>
> > Welche Einschränkungen?
Das sieht aber sehr teuer aus!
Das würde ich garantiert nur benutzen, wenn es sich nicht vermeiden lässt.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
![](http://selfhtml.bitworks.de/Virencheck.gif)
--
Nur selber lernen macht schlau
<http://bergpost.annerschbarrich.de>
Hi!
preg_match("/^((\"[^\"\f\n\r\t\b]+\")|([A-Za-z0-9_][A-Za-z0-9_\!\#\$\%\&\'\\+\-\~\/\^\\\|\\{\\}]*(\\.[A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\
\|\{\}])))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9])(([A-Za-z0-9\-])([A-Za-z0-9]))?(\.(?=[A-Za-z0-9\-]))?)+[A-Za-z]+))$/D",
$e_mail_adresse);
> Das sieht aber sehr teuer aus!
> Das würde ich garantiert nur benutzen, wenn es sich nicht vermeiden lässt.
Am wenigsten lassen sich Kommentare von anderen Programmierern vermeiden, dass nach Vorschift 08/15 ein gültiger Wert auch so und so aussehen kann. Damit haben sie zwar prinzipiell Recht, aber so ein Spezialfall wird in der Praxis nur sehr selten auftreten. Soweit ich weiß, passt dieser Ausdruck auf alle formal korrekten Mail-Adressen[\*]. Und damit er das tut ist er eben so umfangreich, teuer und wenig praxisnah.
Das soll jetzt kein Plädoyer für laxe Prüfungen im Allgemeinen sein. Sicherheit geht immer vor! Wenn aber weniger Mailadressen erlaubt als theoretisch zulässig sind, tut das der Sicherheit keinen Abbruch.
[\*] Ich hatte, glaube ich, irgendwann mal eine lesbar formatierte und kommentierte Version gesehen, hab aber mangels Interesse nicht geprüft, ob das soweit passte. An Gegenstimmen kann ich mich aber auch nicht erinnern.
Lo!
Soweit ich weiß, passt dieser Ausdruck auf alle formal korrekten Mail-Adressen[*]. Und damit er das tut ist er eben so umfangreich, teuer und wenig praxisnah.
Ich hab' herumprobiert und er passt auf alles - lediglich Adressen mit IDN im Domainpart fallen druch den Rost.
Und "teuer" versteh' ich nicht - der geht ratz-fatz in ein paar ms drüber und kostet keineswegs massiv Rechenleistung (wenn das mit "teuer" gemeint ist).
Natürlich sind damit auch extrem absurde adresen möglich - wie z.B. "$$$"@example.com oder ähnliches.
Ich hab' allerdings bereits einige Stammdaten-Tabellen gesehen wo 50% der E-Mail-Adressen ungültig waren - hauptsächlich Geschichten wie Vorname.@example.com die von gängigen ausdrücken überhaupt nicht beachtet werden.
Mir ist klar, dass "Sonderzeichen" in E-Mail-Adressen extrem Praxisfern sind, aber bei diesem Ausdruck kann ich jedenfalls davon ausgehen, dass er formal korrekte Adressen durchlässt und fehlerhafte aussiebt.
Man weiß nie, wer daherkommt und wie der seine Adresse eingibt.
Ich hab schon oft E-Mails bekommen wo der Client den Local-Part pauschal in Anführungszeichen gesetzt hat - das ist absolut ok, wird aber für praktisch allen regulären Ausdrücken "am Markt" als ungültig erkannt.
Wenn aufgrund so einer Tatsache eine 50.000 Einträge lange Liste auf 500 zusammenschrumpft, weil die Newsletterversandroutine sagt "ungültig, packe ich nich in meine Queue" möchte ich nicht derjenige sein, der das dem Kunden erklärt :)
Hi!
Soweit ich weiß, passt dieser Ausdruck auf alle formal korrekten Mail-Adressen[*]. Und damit er das tut ist er eben so umfangreich, teuer und wenig praxisnah.
Und "teuer" versteh' ich nicht - der geht ratz-fatz in ein paar ms drüber und kostet keineswegs massiv Rechenleistung (wenn das mit "teuer" gemeint ist).
Der zeitliche Aufwand für einzelne Rechenaufgaben ist oft im erträglichen Rahmen, solange sie nicht in Massen vorkommen. Es gab ja auch mal die Idee, einen geringen Cent-Betrag für das Senden einer E-Mail zu erheben. Für den einzelnen ist das sicherlich erträglich, für Massenversender summiert sich das ganz schön und sollte das Spamversenden eindämmen. (Das wäre sicher nichts geworden, denn der Vorschlag kam in einer Zeit, als Zombie-PCs noch nicht so sehr Mode waren.)
"Teuer" kommt immer auf den Anwendungsfall an. Bestes Beispiel ist ' versus ". Eins davon ist zwar "teurer", aber beides versinkt normalerweise im Grundrauschen.
Mir ist klar, dass "Sonderzeichen" in E-Mail-Adressen extrem Praxisfern sind, aber bei diesem Ausdruck kann ich jedenfalls davon ausgehen, dass er formal korrekte Adressen durchlässt und fehlerhafte aussiebt.
Man weiß nie, wer daherkommt und wie der seine Adresse eingibt.
Ich hab schon oft E-Mails bekommen wo der Client den Local-Part pauschal in Anführungszeichen gesetzt hat - das ist absolut ok, wird aber für praktisch allen regulären Ausdrücken "am Markt" als ungültig erkannt.
Der Ausdruck wird bei meiner derzeitigen Viewport-Breite in 5 Zeilen angezeigt. Circa 3 davon belegen allein die Prüfung auf korrekte IP-Adressen im Domain-Teil. Und da sind noch nicht mal Adressen à la 127.0.0.1 ausgefiltert oder IPv6 berücksichtigt. IP-Adressen mögen zwar korrekt sein, aber das wird vermutlich k(aum )ein Client statt Doaminnamen verwenden. Ansonsten ist dein Argument natürlich berechtigt. Wenn die Clients gültigerweise quotieren, ist das ärgerlich, wenn das als falsch abgelehnt wird.
Wenn aufgrund so einer Tatsache eine 50.000 Einträge lange Liste auf 500 zusammenschrumpft, weil die Newsletterversandroutine sagt "ungültig, packe ich nich in meine Queue" möchte ich nicht derjenige sein, der das dem Kunden erklärt :)
Erklär ihm, dass heute RSS und Twitter aktuell sind :-)
Lo!
Moin Moin!
Im Artikel Validierung von eMail-Adressen steht zu dieser Funktion übrigens nichts (eh klar, Artikel zu alt).
Doch, ein entscheidender Satz steht drin:
Ein zweites, ernüchterndes Fazit zur Frage "How do I check a valid mail address?" findet sich in der Perl-FAQ: You can't, at least, not in real time.
Ende der Diskussion. Es geht nicht.
Du kannst nicht alle Tippfehler finden, und Du kannst jede Menge Annahmen über Mailbox- und Domain-Teil der E-Mail-Adresse NICHT machen. Die RFCs sind gerade beim Mailbox-Teil extrem flexibel gestaltet. Schon die beiden Annahmen, dass Groß- und Kleinschreibung beim Mailbox-Teil eine oder keine Rolle spielt, ist falsch.
Die neue PerlFAQ9 von Perl 5.10 ist mittlerweile in dem Punkt etwas länger und ausführlicher. Du kannst tatsächlich das Format der E-Mail-Adresse nach den bekannten RFCs durchvalidieren und damit grobe Tippfehler und Layer-8-Probleme aussortieren. Den Domain-Teil mußt Du aber immer noch live gegen das DNS-System abgleichen.
Damit kannst Du aber immer noch keine Aussage darüber treffen, ob eine E-Mail-Adresse gültig ist. Die letzte Prüfung liegt beim annehmenden Mailserver:
Der kann (und sollte) z.B. den Abgleich per VRFY oder EXPN verweigern, so dass nur ein Zustellversuch per MAIL FROM bleibt. Den kann der Server ablehnen wegen falscher Adresse, ablehnen weil Du auf einer Blacklist stehst, ablehnen weil Du nicht auf einer Whitelist stehst, ablehnen weil der Inhalt nicht genehm ist, vorübergehend ablehnen (Greylisting), annehmen und sofort verwerfen, annehmen und per Antwort-Mail über die Nichtzustellbarkeit informieren, annehmen und an einen anderen Server weiterleiten, annehmen und zustellen. Egal was der Server macht, Du kannst selbst während des gesamten SMTP-Dialoges NICHT herausfinden, ob der Mailbox-Teil der E-Mail-Adresse gültig ist.
Damit kannst Du nicht herausfinden, ob die E-Mail-Adresse gültig ist, ohne dass der Empfänger aktiv auf die E-Mail-Adresse reagiert. Z.B. indem er auf einen Link in der E-Mail klickt oder eine Antwort-Mail mit einem festgelegten Inhalt und/oder einer festgelegten E-Mail-Adresse an Dich schickt. Und das kann ziemlich asynchron werden, Reaktionszeiten im Bereich von Tagen sind durchaus möglich, und immer noch kann sich der Empfänger tot stellen und die E-Mail einfach ignorieren.
Wieder aus der neuen PerlFAQ9:
"Our best advice for verifying a person's mail address is to have them enter their address twice, just as you normally do to change a password. This usually weeds out typos. If both versions match, send mail to that address with a personal message. If you get the message back and they've followed your directions, you can be reasonably assured that it's real."
"A related strategy that's less open to forgery is to give them a PIN (personal ID number). Record the address and PIN (best that it be a random one) for later processing. In the mail you send, ask them to include the PIN in their reply. But if it bounces, or the message is included via a "vacation" script, it'll be there anyway. So it's best to ask them to mail back a slight alteration of the PIN, such as with the characters reversed, one added or subtracted to each digit, etc."
Alexander
Doch, ein entscheidender Satz steht drin:
Ein zweites, ernüchterndes Fazit zur Frage "How do I check a valid mail address?" findet sich in der Perl-FAQ: You can't, at least, not in real time.
Wie erwähnt geht es mir darum, syntaktisch korrekte E-Mail-Adressen zuzulassen - und nicht zu prüfen, ob es sich um eine gültige und tatsächlich vorhandene E-Mail-Adresse handelt - denn das ist wohl praktisch unmöglich.
Kaum ein großer E-Mail-Adressen-Anbieter wie z.B. GMX beantwortet die Frage, ob es sich um eine existente Adresse handelt mit "Ja".
Eine E-Mail zu verschickten und die Bounce-Message abzufangen fällt ebenfalls flach - manche Mailserver versenden einfach keine.
Es geht mir wie gesagt schlichtweg darum, dass der Ausdruck keine offensichtlich gültigen Adressen blockt (wie es die meisten Ausdrücke tun, die so herumschwirren) aber auch keine Adressen zulässt, die offensichtlich fehlerhaft eingegeben wurden.
Meine Eltern sind schon im Rentenalter - sie machen eigentlich immer wieder denselben Fehler: Adresse irgendwo in der Form user.@example.com oder user @example.com usw. eingeben.
Genau sowas soll entdeckt werden - ich will nicht wissen, ob mir der user tatsächlich die Adresse eines existenten Mailaccounts vorsetzt oder einen trashmail-Provider nutzt, ich will ihn nur davor schützen, sich mit einer syntaktisch falschen Adresse zu registrieren um dann vergeblich auf eine Antwort zu warten.