Grundstruktur
Dieser Abschnitt befasst sich mit dem Grundgerüst unseres Packages. Am Ende dieser Seite wird das Programm - zumindest theoretisch - bereits lauffähig sein.
Als ersten Schritt erstellen wir unser Package, binden externe Standard-Module ein
und deklarieren eine Subroutine sendMail. An diese Subroutine sollen
über das Hash %mail sämtliche relevanten Daten vom Hauptprogramm
übergeben werden.
package mail;
###
# Module aufrufen
###
use CGI::Carp qw(fatalsToBrowser);
###
# Variablen exportieren
###
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw($mail_error);
@EXPORT_OK = qw();
###
# Standard-Variablen
###
my $mailprog = "/usr/lib/sendmail";
$mail_error = undef;
###################################
###################################
#### Send Mail #####
###################################
sub sendMail {
my %mail = @_;
# Hier folgen alle weiteren Anweisungen
# [...]
}
Hinweise:
- Es empfiehlt sich, sämtliche Daten über ein Hash zu übergeben (
my %mail = @_;), ansatt beispielweise mehrere Skalare zu verwenden. Wie wir später noch sehen werden, sollen nicht alle möglichen Variablen Pflicht-Werte darstellen, und auf diese Weise können auch wirklich nur die Werte übergeben werden, die tatsächlich benötigt werden. - Die globale Variable
$mail_errorgibt uns eine Möglichkeit, Fehlermeldungen an das aufrufende Programm zurückzugeben. Die Variable wird über dasExporter-Modul an das aufrufende Programm exportiert und kann dort weiter verwendet werden. - Die Variable
$mailprogbeeinhaltet den Pfad zu dem Mail-Programm des Servers, standardmäßig auf UNIX-basierten Servern/usr/lib/sendmail. Grundsätzlich muss diese Variable nicht gleich zu Programm-Beginn deklariert werden, es is jedoch vorteilhaft, da dieser Wert angepasst werden muss, falls das Mailprogramm an einem anderen Ort liegt.
Was machen wir nun mit diesem Mail-Programm sendmail? Technisch gesehen übergeben wir unsere
gewünschten Informationen als Daten-Stream an ein File-Handle, das eine Pipe zum
angegebenen Programm geöffnet hat. Das mag jetzt etwas abstrakt klingen, bedeutet aber
konkret nichts anderes, als dass wir die altbekannte print-Anweisung so "umbiegen",
dass sie ihre Anweisungen eben an unser Mail-Programm anstelle des STDOUT-Streams übergibt -
genauso, wie wir mittels open auch jede x-beliebige Datei beschreiben können:
#[...]
sub sendMail {
my %mail = @_;
###
# Mail-Programm starten
###
if ( open(MAIL,"|$mailprog -t") ) {
# Daten an Mail-Programm übergeben
print MAIL "To: $mail{'to'}\n";
print MAIL "From: $mail{'from'}";
print MAIL " ($mail{'namefrom'})" if ( exists($mail{'namefrom'}) );
print MAIL "\n";
print MAIL "Cc: $mail{'cc'}\n" if ( exists($mail{'cc'}) );
print MAIL "Bcc: $mail{'bcc'}\n" if ( exists($mail{'bcc'}) );
print MAIL "Subject: $mail{'subject'}\n";
print MAIL "MIME-Version: 1.0\n";
print MAIL "Content-Type: text/plain;\n\tcharset=\"iso-8859-1\"\n\n";
print MAIL "$mail{'text'}\n\n";
close(MAIL);
return 1;
}
# Fehler beim Öffnen
else {
$mail_error = "Fehler beim Starten des Mail-Programms: $!";
print STDERR $mail_error;
return undef;
}
}
Erklärung:
Mit open(MAIL,"|$mailprog -t") definieren wir ein Filehandle MAIL, das auf das
Mail-Programm zeigt. Da open() bei einem Fehler den Wert false, ansonsten true
zurückgibt, können wir gleichzeitig mit einer if-Anweisung Fehler abfangen. Bei erfolgreichem Ausführen
des Mail-Programms soll dann an das aufrufende Programm der Wert 1, ansonsten undef
zurückgegeben werden. Zudem wird im Falle eines Fehlers die Fehlermeldung auf STDERR geschrieben
und in der globalen Variable $mail_error gespeichert.
Als nächstes werden die Header-Informationen abgearbeitet. An dieser Stelle wird auch deutlich, wieso sich die
Wert-Übergabe mittels eines Hashs anbietet: Optionale Angaben wie Cc, Bcc können durch die
Bedingung if ( exists($mail{'cc'}) ) nur dann angegeben werden, wenn sie wirklich benötigt werden.
Zu guter Letzt geben wir den Content-Type (momentan lassen wir nur plain-text E-Mails zu) und den
Zeichensatz (charset) an, gefolgt von der eigentlichen Nachricht.
Hinweis:
Das Package ist nun bereits theoretisch lauffähig. Allerdings ist es in dieser Form noch absolut davon abhängig, dass es vom aufrufenden Programm nur korrekte Daten erhält. Im Klartext: Momentan könnte man damit noch jede Menge Unsinn anstellen. Dies werden wir im nächsten Abschnitt ändern.












