Teil von SELFHTML aktuell Teil von Artikel Teil von Programmiertechnik

Programmiertechnik:
E-Mail-Kontrolle

nach unten Christian Kruse
nach unten Hinweise zum Thema
nach unten Beispiel und Erläuterungen
nach unten Weiterführende Links

Christian Kruse

E-Mail: E-Mail CK1@wwwtech.de
Homepage-URL: deutschsprachige Seite http://wwwtech.de/

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten

Hinweise zum Thema

Eine E-Mail-Adresse gemäß englischsprachige Seite RFC819 vollständig auf korrekte Syntax zu überprüfen ist mit einem einzelnen RegEx leider nicht möglich. Das liegt daran, dass einige Elemente in E-Mail-Adressen leider verschachtelt auftreten können. Mit Regular Expressions jedoch kann man nur eine endliche Tiefe nachbilden. Was allerdings möglich ist, ist eine relativ zuverlässige Ausschließung von E-Mail-Adressen mit falscher Syntax. Aber Sie sollten sich darüber klar sein, dass E-Mail-Adressen mit gültiger Syntax nicht zwingend auch gültige E-Mail-Adressen sind. Um das festzustellen, müssen Sie zwangsläufig dem User eine E-Mail schicken und sich den Empfang (etwa durch den Besuch eines in der E-Mail mitgeschickten Links) bestätigen lassen. Sinnvoll ist diese (zusätzliche) Überprüfung trotzdem: durch das Validieren der User-Eingaben werden Sicherheitslücken geschlossen (Stichwort: open()-Problem beim Versenden von E-Mails mit Sendmail) und der Traffic wird verringert, denn an ungültige E-Mail-Adressen muss natürlich auch keine E-Mail geschickt werden.

nach obennach unten

Beispiel und Erläuterungen

In den Beispielen wird Perl-Syntax verwandt. Aber der RegEx ist genauso in JavaScript, PHP oder C gültig.

Vorab einige Bemerkungen zum Aufbau von E-Mail-Adressen: E-Mails sind immer nach dem Muster user@host aufgebaut. Dabei darf der User-Part lediglich die Zeichen a-zA-Z0-9_.- enthalten, muss aber mit a-zA-Z0-9 beginnen.

Alternativ kann ein User einen gequoteten String angeben. "Christian Kruse"@wwwtech.de ist z. B. eine gültige E-Mail-Adresse. Innerhalb dieses Strings darf ein beliebiger ASCII-Charakter vorkommen, aber die Zeichen "\ müssen mit einem \ escaped werden: "Christian \"CK\" Kruse"@wwwtech.de. Dadurch komme ich zu dem folgenden Teil-RegEx:

  my $nonascii = "\x80-\xff"; # Alle Zeichen ueberhalb von Char 128 sind kein ASCII mehr.

  my $nqtext        = "[^\\\\$nonascii\015\012\"]"; # Alle Zeichen, die *nicht* geqoutet werden muessen
  my $qchar         = "\\\\[^$nonascii]";                # Matcht auf gequotete Zeichen

  my $normuser      = '[a-zA-Z0-9][a-zA-Z0-9_.-]*';      # wie oben besprochen
  my $quotedstring  = "\"(?:$nqtext|$qchar)+\"";         # Ein gequoteter String besteht aus nicht escaped chars und escaped chars
  my $user_part     = "(?:$normuser|$quotedstring)";     # der User-Part besteht aus dem normalen User-String oder einem gequoteten String

Der Hostname ist etwas schwieriger zu matchen: generell besteht ein Hostname aus n Subdomains, einem Domain-Namen und einer Toplevel-Domain (z. B. "de"). Dabei darf eine Subdomain aus den Zeichen a-zA-Z0-9._- bestehen und muss mindestens zwei dieser Zeichen enthalten. Als erstes Zeichen jedoch kommen nur die Zeichen a-zA-Z0-9 in Frage. Enden muss dieser Teil mit einem Punkt. Dadurch komme ich zu folgendem Teil-RegEx:

my $dom_mainpart  = '[a-zA-Z0-9][a-zA-Z0-9._-]*\\.';       # Der Domain-Teil
my $dom_subpart   = '(?:[a-zA-Z0-9][a-zA-Z0-9._-]*\\.)*';  # Der Subdomain-Teil, 0-n Subdomains
my $dom_tldpart   = '[a-zA-Z]{2,5}';                       # Die Toplevel-Domain
my $domain_part   = "$dom_subpart$dom_mainpart$dom_tldpart";

Jetzt gilt es nur noch, ein eventuelles 'mailto:' zu berücksichtigen. Das geht recht einfach mit einem kleinen Teil-Ausdruck:

my $protocol      = '(?:mailto:)';  # Das 'mailto:' ist optional

Schließlich nochmal der komplette RegEx, zum Herauskopieren:

#!/usr/bin/perl -w

use strict;

### RegEx begin
my $nonascii      = "\x80-\xff"; # Non-ASCII-Chars are not allowed

my $nqtext        = "[^\\\\$nonascii\015\012\"]";
my $qchar         = "\\\\[^$nonascii]";

my $protocol      = '(?:mailto:)';

my $normuser      = '[a-zA-Z0-9][a-zA-Z0-9_.-]*';
my $quotedstring  = "\"(?:$nqtext|$qchar)+\"";
my $user_part     = "(?:$normuser|$quotedstring)";

my $dom_mainpart  = '[a-zA-Z0-9][a-zA-Z0-9._-]*\\.';
my $dom_subpart   = '(?:[a-zA-Z0-9][a-zA-Z0-9._-]*\\.)*';
my $dom_tldpart   = '[a-zA-Z]{2,5}';
my $domain_part   = "$dom_subpart$dom_mainpart$dom_tldpart";

# Der RegEx selbst
my $regex         = "$protocol?$user_part\@$domain_part";
### RegEx end

# Kleiner Test-Schnipsel:

my @emails = (
  'ckruse@wwwtech.de',
  '"Christian Kruse"@wwwtech.de',
  '"Christian \"CK\" Kruse"@wwwtech.de',
  '"Christian"ckruse@wwwtech.de'
);

foreach my $email (@emails) {
  if($email =~ /^$regex$/) {
    print "it is a valid email\n";
  }
  else {
    print "it isn't a valid email\n";
  }
}

# eof

Ich habe in den verschiedenen Sprachen noch dementsprechend Funktionen implementiert:

Perl

Ein kleines Modul, dass im selben Verzeichnis wie das Script mit dem Dateinamen CheckEMail.pm abgespeichert werden muss. Eingebunden wird es dann wie folgt:

use CheckEMail qw/isEmail/;

if(isEmail($email)) {
  print "email is valid!\n";
}

Hier also der Quelltext des Moduls:

package CheckEMail;

use strict;
use vars qw($VERSION @ISA @EXPORT_OK $MailRegEx);

require Exporter;

@ISA       = qw(Exporter);
@EXPORT_OK = qw(isEmail $MailRegEx);
$VERSION   = '1.0';

### RegEx begin
my $nonascii      = "\x80-\xff"; # Non-ASCII-Chars are not allowed

my $nqtext        = "[^\\\\$nonascii\015\012\"]";
my $qchar         = "\\\\[^$nonascii]";

my $protocol      = '(?:mailto:)';

my $normuser      = '[a-zA-Z0-9][a-zA-Z0-9_.-]*';
my $quotedstring  = "\"(?:$nqtext|$qchar)+\"";
my $user_part     = "(?:$normuser|$quotedstring)";

my $dom_mainpart  = '[a-zA-Z0-9][a-zA-Z0-9._-]*\\.';
my $dom_subpart   = '(?:[a-zA-Z0-9][a-zA-Z0-9._-]*\\.)*';
my $dom_tldpart   = '[a-zA-Z]{2,5}';
my $domain_part   = "$dom_subpart$dom_mainpart$dom_tldpart";

$MailRegEx        = "$protocol?$user_part\@$domain_part";
### RegEx end

sub isEmail($) {
  my $mail = shift;
  return $mail =~ /^$MailRegEx$/o;
}

1;

# eof

PHP

Für PHP ist einfach nur eine kleine Funktion geschrieben worden, die true oder false zurück gibt:

function check_email($email) {
  // RegEx begin
  $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,5}';
  $domain_part   = "$dom_subpart$dom_mainpart$dom_tldpart";

  $regex         = "$protocol?$user_part\@$domain_part";
  // RegEx end

  return preg_match("/^$regex$/",$email);
}

Einfach in den Source kopieren und wie folgt benutzen:

if(check_email($email)) {
  echo "E-Mail ist gültig!"
}

JavaScript

Auch für JavaScript gibt es eine Version. Die funktioniert jedoch nur im NN4, Mozilla, IE ab Version 5 und Opera ab Version 6. Vielen Dank an dieser Stelle an E-Mail Antje Hofmann, die den RegEx unter JavaScript lauffähig gemacht hat. Die folgende Funktion mit dem leicht abgewandelten RegExp einfach in das HTML-Dokument zwischen <script></script> setzen und bei Bedarf aufrufen.

function checkEmail(email) {
  var proto  = "(mailto:)?";
  var usr    = "([a-zA-Z0-9][a-zA-Z0-9_.-]*|\"([^\\\\\x80-\xff\015\012\"]|\\\\[^\x80-\xff])+\")";
  var domain = "([a-zA-Z0-9][a-zA-Z0-9._-]*\\.)*[a-zA-Z0-9][a-zA-Z0-9._-]*\\.[a-zA-Z]{2,5}";
  var regex  = "^" + proto + "?" + usr + "\@" + domain + "$";

  var rgx    = new RegExp(regex);
  return rgx.exec(email) ? true : false;
}

Die Funktion liefert bei Aufruf true oder false zurück.

nach obennach unten

Weiterführende Links

Die folgenden Stellen werden empfohlen, um die obigen Beispiele besser zu verstehen, oder um weitere Möglichkeiten und Details zu erfahren.

bereichsübergreifende Seite E-Mail Syntax überprüfen

bereichsübergreifende Seite SELFHTML: Reguläre Ausdrücke
bereichsübergreifende Seite SELFHTML: RegExp-Objekt

deutschsprachige Seite Reguläre Funktionen (Perl-kompatibel)
englischsprachige Seite perldoc perlre

englischsprachige Seite RFC819

Teil von SELFHTML aktuell Teil von Artikel Teil von Programmiertechnik

© 2007 bereichsübergreifende Seite Impressum