Dennis: ärger mit regulärem ausdruck

Beitrag lesen

Hi azok,

ereg("/^([a-zA-Z0-9]+([.]?|[-]?|[_]?)?)(-|_|.)([a-zA-Z0-9]+([.]?[_]?)?)@([a-z0-9]+([.]?|[-]?)?)*[a-z0-9]+.{1}[a-z]{2,6}$/i",$email)

Puh, ich vermute mal, diese Mühe, die du dir hier machst, ist vollständig überflüssig. Ich kann dir trotzdem eine E-Mail Adresse unterjubeln, die gar nicht existiert...

nun, sie funktioniert auch ganz gut... aber leider bei meiner eigenen(!) emailadresse nicht. ich verstehe nicht warum... bei heinrich_peter@hotmail.com liefert sie mir "false"...

Nun, RegEx sind standardmäßig gierig, deshalb glaube ich das Phänomen wie folgt erklären zu können:

([a-zA-Z0-9]+([.]?|[-]?|[_]?)?)(-|_|.)([a-zA-Z0-9]+([.]?[_]?)?)
  |             |                 |        |            |
Buchstaben (1 und mehr)        -, _ oder sonst was    -, _ oder sonst was
                |                          |
             -, _ oder sont was          Buchstaben (1 oder mehr)

Das dürfte dein RegEx bis zum @ Zeichen sein.

Jetzt nehmen wir mal die E-Mail heinrich_peter:

Das heinrich matcht alles noch in den ersten Teil (die Buchstaben), der Unterstrich wird dann allerdings von dem zweiten Teil "gefressen" (der ja 0 oder 1 mal vorkommen soll) und somit bleibt für den dritten Teil keines der Zeichen "(-|_|.)" mehr übrig.

Womit der RegEx dann als ganzes nicht mehr matchen würde.

Ok, dein Problem ist festgestellt, jetzt mal zu deinem Ansatz:

Dein RegEx würde folgende E-Mail nicht als richtig erkennen:

vorname_zweitname_nachname@domain.de

Ferner setzt du durch vorraus, dass der Teil vor dem @ mindestens 3 Zeichen lang sein muss - ist dem denn wirklich so? Kann ich @meinerdomain denn nicht auch nur zwei Zeichen machen?

Dann, was soll das:

([.]?|[-]?|[_]?)?

Ich weiß nicht, was du durch das escapen des Punkte bewirken willst. In einer Zeichenklasse, also zwischen [ und ] hat ein . immer seine normale Bedeutung und gilt nicht "als Platzhalter für ein beliebiges Zeichen (außer Whitespace)", für was er sonst gilt.

Dann ist deine Logik da auch falsch. Da blickt doch keiner mehr durch, mach das lieber so:

([.]|-|_)?

Sollte eigentlich genau das gleiche bewirken: Entweder ein -, oder ein _, oder ein beliebiges Zeichen, oder gar nichts.

Die restlichen logischen Fehler (die sich einander ähneln) lasse ich jetzt mal außer Acht.

Ach ja, einer noch: Woher willst du wissen, ob es nicht schon bald TLD's mit mehr als 6 Zeichen gibt? Mache also lieber {2,} um das zukunftssicher zu halten.

Trotzdem mal noch ein Lösungsansatz für deinen RegEx: Du könntest den Modifier U (für ungreedy, also "unhungrig"/nicht gefräßig) verwenden.

Allerdings will ich dich nicht dazu anstiften einen eh schon vermurksten RegEx noch weiter zu bearbeiten. RegExen ist - wie man zu weilen zu Recht sagt - eine Kunst, also versuche immer, alles so einfach wie möglich zu machen, ein Beispiel habe ich dir schon gegeben.

Und dann habe ich hier mal noch eine experimentelle Funktion, die ich mir (auf einenem bestehenden Code basierend) zur überprüfung gebaut habe.

Mir ist bewusst, dass diese Funkion nur auf entsprechend Konfigurierten Server laufen kann und auch dort der Erfolg nicht immer gewährleistet ist.

//Funktion Check E-Mail Absender
function check_email($email, $check_host = false)
{
  $nonascii      = "\x80-\xff"; # Non-ASCII-Chars are not allowed
  $nqtext        = "[^\\$nonascii\015\012"]";
  $qchar         = "\\[^$nonascii]";
  $protocol      = '(?:mailto:)';
  $normuser      = '[a-zA-Z0-9][a-zA-Z0-9_.-]*';
  $quotedstring  = ""(?:$nqtext|$qchar)+"";
  $user_part     = "(?:$normuser|$quotedstring)";
  $dom_mainpart  = '[a-zA-Z0-9][a-zA-Z0-9._-]*\.';
  $dom_subpart   = '(?:[a-zA-Z0-9][a-zA-Z0-9._-]*\.)*';
  $dom_tldpart   = '[a-zA-Z]{2,}';
  $domain_part   = "$dom_subpart$dom_mainpart$dom_tldpart";
  $correct_opt   = preg_match("/^$protocol?$user_part@($domain_part)$/",$email,$treffer);
  //Wenn die E-Mail Adresse optisch schon verkehrt ist abbrechen
  if(!$correct_opt) return false;

//Überprüfung auf Host,
  //der folgende Teil ist experimentell!!!
  if($check_host)
  {
    //Sonst überprüfen, ob es die Domain in der Adresse gibt
    $correct_nopt  = @fopen("http://www.".$treffer[1],"r");
    //Wenn nicht abbrechen
    if(!$correct_nopt) return false;
    //Sonst E-Mail Adresse als gültig durchlasen
    fclose($correct_nopt);
  }

//Und True zurückliefern
  return true;
}

Was ich versuche ist, den Host aus dem Domain Teil anzusprechen. Dass da natürlich auch richtige E-Mails verweigert werden können, weil der Server z.B. grade down ist, ist klar.

Na ja, da müsste man sicherlich noch was dran machen....

MfG, Dennis.

--
Mein SelfCode: ie:{ fl:{ br:^ va:) ls:< fo:) rl:( n4:& ss:) de:> js:( ch:{ sh:( mo:} zu:|
Zufällige Hinweise:
------------------------
Wissen ist gut, Können ist besser, aber das Beste und Interessanteste ist der Weg dahin! (Gernot Back)