Homepage Inspire-world | Forum
CGI/Perl Workshops Mailversand Teil 1

 Inhaltsverzeichnis/Workshops Übersichtsseite/Mailversand Teil 1
Hier in diesem Workshop will ich nun das Thema Mailversand behandeln. Zu Anfang ein einfaches Formular mit einer Empfänger und Betreffauswahl welches dann durch ein Mailscript versendet wird.

1. Das Formular zum eintragen der Daten

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<title>Anfrageformular</title>
</head>

<body bgcolor="#ffffff" vlink="#800080" alink="#ff0000" link="#0000ff">

<form action="../cgi-bin/feedback.pl" method="POST">
<div align="center">
<table width="500" border="1" cellspacing="0" cellpadding="0" bgcolor="#ECECEC">
<tr>
<td>
<table width="500" bgcolor="#ECECEC">
<tr><td><div align="center">
<font face="Verdana, Arial" size="2"><b>Feedbackformular</b></font></div>

<table>
<tr>
<td align="right"><font face="Verdana, Arial" size="1">An wen senden?</font></td>
<td>
<select name="empfaenger" size="1">
<option value="0">Webmaster Inspire-net</option>
<option value="1">Privatadresse</option> 
</select></td>
</tr>

<tr>
<td align="right"><font face="Verdana, Arial" size="1">Betreff?</font></td>
<td>
<select name="subject" size="1">
<option value="Allgemeine Anfrage">Allgemeine Anfrage</option>
<option value="Webdesign Anfrage">Anfrage zu Webdesign</option>
<option value="CGI und PHP Anfrage">Anfrage CGI und PHP</option>
</select></td>
</tr>

<tr>
<td align="right"><font face="Verdana, Arial" size="1">Ihr Name</font></td>
<td><input type=text size=40 maxlength=256 name="name"></td>
</tr>

<tr>
<td align="right"><font face="Verdana, Arial" size="1">Ihr Vorname</font></td>
<td><input type=text size=40 maxlength=256 name="vorname"></td>
</tr>

<tr>
<td align="right"><font face="Verdana, Arial" size="1">E-Mail Adresse</font></td>
<td><input type=text size=40 maxlength=256 name="mailadresse"></td>
</tr>

<tr>
<td colspan="2"> </td>
</tr>

<tr>
<td align="right" valign="top"><font face="Verdana, Arial" size="1">Ihr Text</font></td>
<td><textarea name="anfragetext" cols="40" rows="8"></textarea></td>
</tr>

</table>
<br>
<div align="center"><input type=submit value="Nachricht senden">
<input type=reset value="Formular zurücksetzen"></div>

</form>
</td>
</tr>
</table>
</body>
</html>
Hinweise zum Formular

Da das Formular an verschiedene Empfänger gesendet werden kann ist hier eine Auswahlliste integriert.
<select name="empfaenger" size="1">
<option value="0">Webmaster Inspire-net</option>
<option value="1">Privatadresse</option> 
</select></td>
Um nun eine korrekte Empfängerauswahl zu gewährleisten muss beim Value Wert von 0 her angefangen werden.
Perl fängt bei 0 an zu zählen!




1. Das Script zum versenden der Daten

#!/usr/bin/perl

# Der Pfad zu Ihrem Mailprogramm
$mailprog = '/usr/sbin/sendmail';

# Der Pfad zu Ihren Date-Kommando
$date = '/usr/bin/date';

# An welche URL soll der User geleitet werden, wenn er seine Mail 
# geschrieben hat?
$returnurl = "http://www.ihredomain.de/";

# Zeitspanne in Sek nach der weitergeleitet wird zu obiger URL
$weiterleitungszeit = 5;

# E-Mail des Empfängers UNBEDINGT den \ vor dem @ notieren
@email_liste = ("webmaster\@ihredomain.de","privat\@mailadresse.de");

###################################################

read(STDIN, $input, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $input);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
###################################################
# Hier JEDES Formularelement eintragen was in dem Formular 
# vorkommt von welchem der User absendet
# Die Reihenfolge spielt hier keine Rolle

$empfaenger = $FORM{'empfaenger'};
$subject = $FORM{'subject'};
$name = $FORM{'name'};
$vorname = $FORM{'vorname'};
$mailadresse = $FORM{'mailadresse'};
$anfragetext = $FORM{'anfragetext'};

###################################################
# Liste der Pflichtfelder die der Absender ausfuellen muss. 
# Kann beliebig angepasst werden

# Fehlerbehandlung Anfang
$fehlermeldung = "" ;
$fehler_gefunden = "" ;

$errormeldung = "<li>Das Feld Name wurde nicht ausgefüllt.\n" ;

if ($name eq "") {
$fehlermeldung = $fehlermeldung.$errormeldung ;
$fehler_gefunden = 1 ; }

$errormeldung = "<li>Das Feld Vorname wurde nicht ausgefüllt.\n" ;

if ($vorname eq "") {
$fehlermeldung = $fehlermeldung.$errormeldung ;
$fehler_gefunden = 1 ; }


$errormeldung = "<li>Bitte geben Sie eine gültige E-Mail Adresse ein.\n" ;

if ($mailadresse !~ /.+\@.+\..+/) {
$fehlermeldung = $fehlermeldung.$errormeldung ;
$fehler_gefunden = 1 ; }


$errormeldung = "<li>Das Feld E-Mail wurde nicht ausgefüllt.\n" ;

if ($mailadresse eq "") {
$fehlermeldung = $fehlermeldung.$errormeldung ;
$fehler_gefunden = 1 ; }

if ($fehler_gefunden) {
&fehlerausgabe; }

# Fehlerbehandlung Ende
###################################################

&datumsausgabe;
&mailsenden; 
&bestaetigung;

sub mailsenden {
open (MAIL, "|$mailprog -t") || die $!;
print MAIL "To: $email_liste[$empfaenger]\n";
print MAIL "From: $vorname $name\n";
print MAIL "Subject: $subject\n\n";
print MAIL "Eine Anfrage von ihrem Feedbackformular\n";
print MAIL "Name: $name \n";
print MAIL "Vorname: $vorname\n";
print MAIL "E-Mail: $mailadresse\n";
print MAIL "==================================\n";
print MAIL "Anfragetext:\n";
print MAIL "$anfragetext\n";
print MAIL "==================================\n\n";
print MAIL "Gesendet um: $datum\n";
close(MAIL);
}
###################################################
sub datumsausgabe {

# Datumsroutine

@tage = ('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag');
@monate = ('Januar','Februar','Maerz','April','Mai','Juni','Juli','August',
'September','Oktober','November','Dezember');
($sec, $min, $stunde, $mtag, $mon, $jahr, $tag, $nr_tag, $isdst) = localtime(time);
if($stunde < 10) { $stunde = "0$stunde"; }
if ($min < 10) { $min = "0$min"; }
if ($sec < 10) { $sec = "0$sec"; }
$jahr = 1900 + $jahr;
$datum = "$stunde:$min Uhr $tage[$tag], $mtag. $monate[$mon] , $jahr";
}
###################################################
sub bestaetigung {
print "Content-type: text/html\n\n";
print <<"ENDE"
<html>

<head>
<title>Danke!</title>
<meta http-equiv="refresh" content="$weiterleitungszeit; URL=$returnurl">
</head>

<body>
<div align=center><table bgcolor=#F2F2F2 width=500 cellspacing=4 cellpadding=4><tr><td>
<font size=2 face=verdana, Arial><b>Vielen Dank!</b><br>
Vielen Dank Herr/Frau $vorname $name, für Ihre Anfrage.<br>
Sie werden in $weiterleitungszeit Sekunden weitergeleitet,<br>
falls nicht, klicken Sie bitte untenstehen Link.<br>
<a href="$returnurl">Zurück zur Hauptseite</a></font></p>
</td></tr></table></div></body>

</html>

ENDE
}

###################################################
sub fehlerausgabe {
print "Content-type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<title>Fehler aufgetreten</title>\n";
print "</head>\n";
print "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\">\n";
print "<div align=\"center\">\n";
print "<table bgcolor=\"#800000\" width=\"500\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\">\n";
print "<tr><td>\n";
print "<table bgcolor=\"#F1F1F1\" width=\"500\" cellspacing=\"0\" cellpadding=\"4\" border=\"0\">\n";
print "<tr>\n";
print "<td><font face=\"Verdana, Arial\" size=\"2\">\n";
print "Beim ausfüllen haben Sie folgendes vergessen:<ol> <b>$fehlermeldung</b>\n";
print "</ol><br>\n";
print "Bitte gehen Sie zurück und versuchen es erneut!<br><br>\n";
print "</font></td></tr></table></td></tr></table></div></body></html>\n";
exit;
	}
###################################################

Hinweise zum Script

Wenn der Webserver Daten an ein CGI Script sendet enthalten diese Daten eine vielzahl an Zeichen, diese werden wie in der folgenden Übersicht verschlüsselt. Dabei werden Zahlen und Buchstaben ganz normal übertragen, Leerzeichen werden zu + umgewandelt, alle anderen Zeichen werden in %HH (Hexadezimalzeichen des entsprechenden ASCII Codes) umgesetzt.
Dieses nennt man URLKODIERUNG.
Normales Zeichen    URL verschlüsselter String

\t (tab)            	%09
\n (Zeilenwechsel)	%0A
/                   	%2F
~                   	%7E
:                   	%3A
;                   	%3B
@                   	%40
&                   	%26
Hier ersteinmal einige Worte zu diesem Codeabschnitt. Keine Bange, braucht nicht auswendig gelernt zu werden. :-) Das ganze kann man als Quasi Standardcode verwenden für die Verarbeitung von ankommenden Formulardaten. Etwas weiter unten werd ich das mal in Einzelteile zerlegen.
read(STDIN, $input, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $input);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
read(STDIN, $input, $ENV{'CONTENT_LENGTH'});
Hier wird über die Standardeingabe gelesen und alles in die Skalarvariable $input gespeichert. Gelesen wird die gesamte länge der Informationen CONTENT_LENGTH , diese ENV Variable wird durch den Server bestimmt.

@pairs = split(/&/, $input);
Hier wird nun das ganze in ein Array von Wertepaaren gesplittet.

foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
Hier nun wird mit einer foreach Schleife das ganze durchlaufen.

$name =~ tr/+/ /;
Diese Linie ersetzt alle + Zeichen durch ein Leerzeichen.

$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
Dieser, etwas kompliziert aussehende reguläre Ausdruck konvertiert nun die oben angesprochenen Hexadezimalen %HH zu normalen ASCII Zeichen mittels der pack() Funktion zurück. Die Pack Funktion ist auf der Perl Manpage sehr ausführlich beschrieben.

Zum Schluss werden dann die aufbereiteten Paare $FORM{$name} = $value; zurückgegeben.


Abschnitt Fehlerbehandlung

Hier brauch ich nicht viel zu sagen, die Funktionsweise ist leicht erklärt. Es werden die $vorname Variablen mit Vorgaben oder Mustern verglichen. Stimmt etwas nicht mit der Vorgabe überein wird die Subroutine sub fehlerausgabe aufgerufen und der Fehler angezeigt. weitere Fehlerbehandlungsroutinen sind unter Formprüfung zu finden.
Der eigentliche Mailversand:
Vergleichen kann man das senden einer Mail mit dem öffnen einer Datei. Nur werden hier die Daten mittels Sendmail versendet und nicht in eine Datei geschrieben. Beachten sollte man das nach der Betreffzeile print MAIL "Subject: $subject zwei \n\n virtuelle Zeilenumbrüche folgen sollten.
Mit close(MAIL); wird das ganze dann wieder geschlossen.
open (MAIL, "|$mailprog -t") || die "Fehler Sendmail");
print MAIL "To: $email_liste[$empfaenger]\n";
print MAIL "From: $vorname $name\n";
print MAIL "Subject: $subject\n\n";
print MAIL "Eine Anfrage von ihrem Feedbackformular\n";
...
close(MAIL);
Hinweis: Anstatt MAIL kann man in der print MAIL auch print EMAIL oder ähnliches notieren. Am meisten wird aber MAIL verwendet. So sieht man auch leichter was zu was gehört.
Datums und weitere Subroutinen

Die hier im Script eingesetzte Datumsroutine ist nicht bindend, wird aber gebraucht um in der Mail das Datum anzugeben.

Die weiteren Subrotinen sollten keiner Erklärung bedürfen. Diese können individuell gestaltet werden. Um es nocheinmal zu verdeutlichen habe ich die Subroutine sub bestaetigung mittels print <<"ENDE" ... ENDE und die Fehlersubroutine in Perl Printanweisungen notiert. Bei letzterem muss peinlich genau darauf geachtet werden die \ vor die " zu setzen. Vergisst man dies ist einem ein Error sicher....

Im nächsten Kapitel werde ich noch weitere Möglichkeiten des Mailens und was damit zusammenhängt beschreiben.



 Zum Inhaltsverzeichnis/Workshops Übersichtsseite/Mailversand Teil 1
Autor: Helmut Walter Homepage Inspire-world Fragen, Anregungen und Hinweise bitte in das Forum

Valid HTML 4.0! Valid CSS!