Validierung von eMail-Adressen (Selfforumssieb)

Auslöser zur Diskussion war der SELFHTML-Featureartikel »Programmiertechnik: E-Mail-Kontrolle«, in dem Christian Kruse beschreibt (besser: regext), wie man eine vom Nutzer angegebene eMail-Adresse gemäß RFC819 zerpflückt.

Vinzenz Mai kommentiert:

Diese ist – wie die meisten derartigen Prüfungen – fehlerhaft.
Beispiel: Top-Level-Domain .museum ist nicht gestattet.

Siechfreds Einwurf, man könne den regulären Ausdruck innerhalb des Featureartikels dahingehend erweitern, dass er TLDs mit einer Länge von bis zu sechs Zeichen akzeptierte, wird mit einem früheren Zitat von Manuel B. kommentiert:

Und [..] was ist mit TLDs, die es noch nicht gibt? Ein Script, das bewusst zukünftige Entwicklungen begrenzt, ist IMHO eine völlige Fehlplanung.

Vinzenz spricht von der Notwendigkeit eines Webautors, abgelieferte Auftragsarbeiten dauerhaft kontrollieren zu müssen, falls derartige eMail-Prüfungen eingesetzt würden und verweist auf ein Posting MudGuards, das eine Übersicht neuer TLDs aus nicht-englischen Adresszonen enthält, die zukünftig in Gebrauch kommen könnten. Vinzenz:

Wenn diese TLDs in Betrieb gehen, darf der Benutzer solcher
TLDs erwarten, seine Mail-Adresse auch in der ihm geläufigen Schrift einzugeben – und nicht in Punycode buchstabieren zu müssen.

Selbst lesen: Die gesamte Diskussion im SELFHTML-Forum.
Vielen Dank an alle Beteiligten!

Fazit

Ein erstes Fazit kam rückblickend gleich am Anfang von Vinzenz, der bestätigt, was auch schon an anderen Stellen des Selfforums diskutiert wurde:

Viele beschränken ihre Überprüfung auf das Vorhandensein von @
und einem . irgendwo dahinter.

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.

Weiterführende Links:

  1. RFCs: RFC819, RFC2606, RFC2822, RFC822
  2. Perl-FAQ: How do I check a valid mail address? mit Link auf Tom Christiansens umfangreiches Script, das gegen die gesamte RFC-Spezifikation prüft, die Angabe einer Blackliste von eMail-Adressen akzeptiert und prüft, ob der angegebene Hostname einer Adresse aufgelöst werden kann. (»It’s not fast, but it works for what it tries to do.«) [Anmerkung: Das Script ist – auch aus den oben genannten Gründen – in der Praxis sicherlich nicht sinnvoll.]
  3. Heise: ICANN testet nicht-englische Adresszonen (10.10.2007)

7 Kommentare » Schreibe einen Kommentar

  1. Götz, dein Link zeigt ziemlich eindrucksvoll, warum eine Validierung von Mailadressen auch mit diesem verhältnismäßig großen Aufwand nicht funktionieren kann.

    Das Log für die Prüfung der Adresse "blafasel@selfhtml.org" ergibt:

    Checking server mail.selfhtml.org...
    Opening up socket to mail.selfhtml.org... Succes!
    mail.selfhtml.org replied: 220 odin.selfhtml.org ESMTP
    
    HELO outkast.tienhuis.nl
    250 odin.selfhtml.org
    (10.62 ms)
    MAIL FROM: <postmaster@tienhuis.nl>
    250 2.1.0 Ok
    (12.17 ms)
    RCPT TO: <blafasel@selfhtml.org>
    450 4.7.1 <blafasel@selfhtml.org>: Recipient address rejected: Greylisted
    (98.93 ms)
    QUIT
    221 2.0.0 Bye
    (8.40 ms)
    Succesful communication with mail.selfhtml.org, no hard errors, assuming OK
    Address appears to be valid...

    Folgende Vorgehensweisen sind aus meiner Sicht denkbar:

    1. Clientseitige Prüfung kann sich nur auf Äußerlichkeiten beschränken. Die typische Äußerlichkeit einer internetweit zugänglichen Mailadresse ist das Vorhandensein von @ und danach von mindestens einem Punkt, umgeben von Zeichen. Vgl. den Forumsthread.
    2. Eine oberflächliche serverseitige Prüfung führt denselben Check durch.
    3. Sofern man dumme Tippfehler des Benutzers abfangen will, empfiehlt es sich, die Mailadresse in zwei unterschiedlichen, ggf. sogar (optisch) weiter auseinanderliegenden Formularfeldern eingeben zu lassen, und dann auf Identität zu vergleichen. Wer sich einmal vertippt, tut das vielleicht kein zweites Mal. Das läßt sich sowohl client- wie serverseitig realisieren.
    4. Ein einfacher Realitätscheck auf eine tatsächlich existierende Mailadresse ist die Prüfung im DNS, ob die angegebene Domain existiert. Allerdings kostet so eine Prüfung schon deutlich mehr Zeit (in der Größenordnung von mehreren hundert Millisekunden bis Sekunden im Erfolgsfall, und in der Größenordnung von mehr als 30 Sekunden, sofern ein DNS-Timeout auftritt, weil irgendwas gerade unerreichbar ist) und ist nur auf dem Server möglich. Insbesondere die lange Wartezeit auf das DNS-Ergebnis im Fehlerfall lassen die Verwendung dieser Methode eigentlich nicht wirklich zu, ohne dass man sich für genau diesen Fall irgendeine Strategie für die Beschäftigung/Besänftigung des wartenden Benutzers überlegt – analog zu allen Skriptaufrufen, die aus anderen Gründen sehr lange dauern können.
    5. Eine im Gegensatz dazu sehr einfache, aber dummerweise asynchrone Methode ist der tatsächliche Versand einer EMail an die angegebene Adresse über den lokal installierten Mailserver (mit entsprechender Warteschlange), mit der Bitte zum Aufruf einer in der Mail angegebenen URL, um den erfolgreichen Empfang zu bestätigen. Dadurch, dass das aktuell laufende Skript nur den Mailversand triggern kann, aber nicht den Erfolg überprüft, ist es leider nicht möglich, den Benutzer direkt auf fehlerhafte Mailangaben hinzuweisen und ihm die Korrektur zu ermöglichen.
    6. Die Krönung ist, wie in Götz‘ Link durchgeführt, der skriptgesteuerte Mailversand mit direkter Überprüfung des SMTP-Ergebnisses – welche allerdings programmtechnisch extrem aufwendig ist, da man alle Eventualitäten des SMTP-Protokolls inklusive Queuing/Versandwiederholung bei temporären Fehlern bzw. Greylisting berücksichtigen müßte. Diese Methode kombiniert zwar alle Vorteile der obigen Methoden, also synchrone und bestmögliche Rückmeldung eines Erfolges an den Benutzer, allerdings auch alle Nachteile: Potentiell lange Wartezeit auf DNS, Unverfügbarkeit von SMTP, temporäre Mailfehler, eigene Realisierung einer Mailqueue. Und trotz dieses enormen Aufwandes ist man, solange der Benutzer nicht tatsächlich den Link in der Mail angeklickt hat, nicht sicher, dass die Mailadresse tatsächlich existiert, funktioniert, ungefiltert ist und vom Besitzer des Postfachs (der nicht identisch sein muß mit der Person, die gerade das Formular ausgefüllt hat) gewollt genutzt wird.

    Da man also auch mit enormem Aufwand keine hundertprozentige, und insbesondere keine synchrone Prüfung auf tatsächliche Korrektheit erlangen kann, stellt sich somit die Frage, warum man dann noch riesigen Aufwand in die Formulierung eines pseudokorrekten regulären Ausdrucks stecken soll.

  2. Kann es denn überhaupt einen regulären Ausdruck geben, mit dem man die syntaktische Gültigkeit einer Emailadresse überprüfen kann? Ich interpretiere (mit meinem Wissen aus der Theoretischen Informatik) den RFC so, dass die rekursive Definition gerade die Möglichkeit eines RegExp ausschließt. Oder täusche ich mich da?

  3. Das soll angeblich der RFC-2822-konforme Regex sein (Zeilenumbrüche sind von mir):

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

    Ich weiß nicht, ob der funktioniert, ich hab ihn bloß auf dieser Seite gefunden: http://www.regular-expressions.info/email.html

    Dort wird auch erläutert, dass wahrscheinlich kein Software mit allen E-Mail-Addressen umgehen kann, und man sich deswegen nicht so streng an das RFC halten sollte.

  4. Hallo Schür,

    vielen Dank für den Hinweis auf diese kleine Diskussion. Ich hab mich extra durch den ganzen Thread geklickt, um zu dem Ergebnis zu kommen, daß mein Link zumindest in dieser Diskussion bisher nicht genannt wurde, weswegen ich ihn nun mal einwerfe.

    Meist sollte irgendeine "Grob-Prüfung" ausreichen, im Zweifel kann man ja bei wichtigeren Anwendungen "Aktivierungs-Mails" verschicken.

    Wenn man trotzdem mal "wirklich" prüfen will, ob eine angegebene E-Mail-Adresse tatsächlich exisitert, ob sie dem gehört, der sie angibt läßt sich sowieso nie prüfen, dann könnte man sich PHP Email address validation with Verify probe mal genauer anschauen.
    Natürlich kann es auch da Probleme geben, aber es ist eine vielleicht durchaus akzeptable Möglichkeit viele Müll-Adressen zu erkennen und nicht zuzulassen.

  5. Meines Wissens gibt es keinen einzelnen RFC, der exakt und klar und deutlich den Rahmen dessen absteckt, was als gültige E-Mailadresse zählt. Ich habe mich vor ein paar Jahren mal etwas mit der Materie befasst, weil ich eine verlässliche Prüfung per Javascript für Kontaktformulare bauen wollte. Ich kam aus dem Staunen nicht mehr heraus und habe am Ende mehr oder weniger aufgegeben. Zur Zeit verwende ich eine Prüfung, die ein paar ausgesuchte Kriterien prüft, aber weit jenseits einer vollständigen Prüfung steht. Damit kann ich halbwegs wirksam verhindern, dass Leute völligen Unfug in ein E-Mail-Adressfeld eingeben.

    Ich weiß nicht, ob ich seinerzeit Wesentliches übersehen habe, aber ich konnte nicht einmal sicher ermitteln, wie lange die Teile vor und nach dem ‚@‘ maximal sein dürfen.

    Und immerhin sind z.B. solche Geschichten wie die folgenden Beispiele gültige E-Mailadressen:

    Hubertus von der hohen Alm <hubertus.hohe-alm@www.meinserver.de>
    jubeltrubelundeitleheiterkeitimfachbereich@uniserver

    Ich habe damals Jeffrey Friedls berühmt-berüchtigtes Buch "Reguläre Ausdrücke" herangezogen. Er befasst sich gegen Ende mit dieser Fragestellung und kommt zu dem Schluss, dass es angesichts der Komplexität der Möglichkeiten im Grunde witzlos ist, eine wirklich exakte Syntaxprüfung erreichen zu wollen. Sein ausgetüfteltes Beispiel einer Perl-RegEx, die annähernd dem Problem gerecht wird, ist knapp 6600 Bytes lang.

    Spätestens nach 100 Bytes stellte mein Fachverständnis sanft den Dienst ein …