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.












