Deutsche PerlFAQ

NAME

perlfaq9 - Netzwerke


DESCRIPTION

Dieser Abschnitt behandelt Fragen bezüglich Netzwerken, dem Internet und einiges über das Web.

Wie ist die korrekte Form einer Antwort von einem CGI-Skript?

(Alan Flavell <flavell+www@a5.ph.gla.ac.uk> antwortet...)

Das Common Gateway Interface (CGI) spezifiziert eine Softwareschnittstelle zwischen einem Programm (``CGI-Skript'') und einem Webserver (HTTPD). Es ist nicht Perl-spezifisch und es seine eigenen FAQs und Tutorials und Usenet-Gruppe, comp.infosystems.www.authoring.cgi

Die CGI-Spezifikation ist in einem informatorischem RFC skizziert: http://www.ietf.org/rfc/rfc3875

Weiter relevante Dokumentationen sind unter http://www.perl.org/CGI_MetaFAQ.html aufgelistet.

Diese Perl FAQs behandeln einige sehr ausgesuchte CGI-Sachen. Wieauchimmer, Perl-Programmierer sind sehr gut beraten, das CGI.pm Modul zu benutzen, das sich um die Details für sie kümmert.

Die Ähnlichkeiten zwischen CGI-Antwort-Headern (definiert in der CGI-Spezifikation) und HTTP-Antwort-Headern (definiert in der HTTP-Sepzifikation, RFC2616) sind gewollt, können aber manchmal verwirrend sein.

Die CGI-Spezifikation definiert zwei Arten von Skripten: Die ``Parsed Header'' Skripte und die ``Non Parsed Header'' (NPH) Skripte. Überprüfe die Dokumentation Deines Servers, was er unterstützt. ``Parsed Header'' Skripte sind in verschiedener Hinsicht einfacher. Die CGI-Spezifikation erlaubt alle der üblichen Darstellungen des Zeilenumbruchs in der CGI Antwort (es ist die Aufgabe des Servers darauf basierend eine richtige HTTP Antwort zu erzeugen). Also ist ``\n'' im Textmodus geschrieben technisch korrekt und empfohlen. NPH Skript sind kniffliger: Sie müssen einen kompletten und fehlerfreien Satz an HTTP-Transaktions Antwort-Headern ausgeben; die HTTP-Spezifikation verlangt, dass die Datensätze mit Carriage-Return und Line-Feed abgeschlossen sind, z.B. ASCII \015\012 im Binärmodus geschrieben.

Die Verwendung von CGI.pm bedeutet exzellente Plattformunabhängigkeit, einschließlich EBCDIC-Systemen. CGI.pm wählt die passende Zeilenumbruch-Darstellung ($CGI::CRLF) und setzt den Binärmodus wo es passt.

Mein CGI-Skript läuft von der Kommandozeile aus, aber nicht im Browser. (500 Server Error)

Verschiedene Dinge können falsch sein. Du kannst den ``Troubleshooting Perl CGI Skript''-Leitfaden unter

  http://www.perl.org/troubleshooting_CGI.html

durcharbeiten.

Wenn Du danach zeigen kannst, dass Du die FAQs gelesen hast und dass Dein Problem etwas einfaches ist, das leicht beantwortet werden kann, wirst Du wahrscheinlinch eine nette und hilfreiche Antwort auf Deine Frage bekommen, wenn Du sie auf comp.infosystems.www.authoring.cgi stellst (wenn es etwas mit HTTP oder mit dem CGI-Protokoll zu tun hat). Fragen, die scheinbar Perl-Fragen sind aber in Wirklichkeit CGI-Fragen und auf comp.lang.perl.misc gestellt werden, kommen nicht so gut an.

Die hilfreichen FAQs, verwandte Dokumente und Leitfaden für die Fehlersuche sind in der CGI Meta-FAQ aufgelistet:

    http://www.perl.org/CGI_MetaFAQ.html

Wie kann ich bessere Fehlermeldungen von einem CGI-Programm bekommen?

Benutze das CGI::Carp Modul. Es ersetzt warn und die und zusätzlich die carp-, croak- und confess-Funktionen aus dem normalen Carp Modul durch ausführlichere und sichere Versionen. Es schickte diese immer noch zur normalen Fehler-Logdatei des Servers.

        use CGI::Carp;
        warn "This is a complaint";
        die "But this one is serious";

Die folgende Verwendung von CGI::Carp leitet die Felhler in eine Datei Deiner Wahl um, und ist innerhalb eines BEGIN-Blocks, um auch Fehler während der Kompilier-Zeit abzufangen.

        BEGIN {
                use CGI::Carp qw(carpout);
                open(LOG, ">>/var/local/cgi-logs/mycgi-log")
                        or die "Unable to append to mycgi-log: $!\n";
                carpout(*LOG);
        }

Du kannst für Schwerwiegende Fehler sogar erreichen, dass sie an den Client-Browser zurückgehen, was für Dein eigenes Debugging schön ist, aber den Endbenutzer verwirren könnte.

        use CGI::Carp qw(fatalsToBrowser);
        die "Bad error here";

Selbst wenn der Fehler auftritt, bevor Du den HTTP-Header ausgeben konntest, wird das Modul versuchen sich darum zu kümmern, um den gefürchteten 500 Server Error zu vermeiden. Normale Warnungen mit dem Namen der Anwendung und Zeitstemplet vorangestellt, landen weiterhin in der Fehler-Logdatei des Servers (oder wo auch immer Du sie mit carpout hinschickst)

Wie entferne ich HTML aus einem String?

Der korrekteste Weg (wenn auch nicht der schnellste) ist, HTML::Parser vom CPAN zu benutzen. Ein anderer weitgehend korrekter weg ist, HTML::FormatText zu benutzen, das nicht nur HTML entfernt, sondern auch ein wenig einfache Formatierung zu dem resultierenden einfachen Text hinzuzufügen.

Viele Leute unternehmen den einfältigen Versuch mit einem einfältigen Regulären Ausdruck, wie z.B. s/<.*?>//g, aber das schlägt in vielen Fällen fehl, wei die Tags vielleicht über mehrere Zeilen gehen, gequotete spitze Klammern enthalten, oder ein HTML-Kommentar enthalten ist. Dazu vergessen die Leute Entitäten zu konvertieren -- wie zum Beispiel &lt;.

Hier ist ein ``einfältiger'' Versuch, der für die meisten Dateien funktioniert:

        #!/usr/bin/perl -p0777
        s/<(?:[^>'"]*|(['"]).*?\1)*>//gs

Wenn Du eine komplettere Lösung haben willst, schau Dir das 3-stufige striphtml Programm unter http://www.cpan.org/authors/Tom_Christiansen/scripts/striphtml.gz an.

Hier ein paar verzwickte Fälle, an die Du denken solltest, wenn Du eine Lösung suchst:

        <IMG SRC = "foo.gif" ALT = "A > B">
        <IMG SRC = "foo.gif"
         ALT = "A > B">
        <!-- <A comment> -->
        <script>if (a<b && a>c)</script>
        <# Just data #>
        <![INCLUDE CDATA [ >>>>>>>>>>>> ]]>

Wenn HTML-Kommentare andere Tags enthalten, würden die Lösungen auch an einem Text wie diesen scheitern:

        <!-- This section commented out.
                <B>You can't see me!</B>
        -->

Wie kann ich URLs extrahieren?

Du kannst leicht alle Arten von URL aus HTML mit HTML::SimpleLinkExtor herausfiltern, das mit Ankern, Bildern, Objekten, Frames und vielen anderen Tags umgehen kann, die eine URL enthalten können. Wenn Du etwas komplexeres benötigst, kannst Du Deine eigene Subklasse von HTML::LinkExtor oder HTML::Parser schreiben. Du könntest sogar HTML::SimpleLinkExtor als Beispiel für etwas nehmen, dass speziell auf Deine Bedürfnisse zugeschnitten ist.

Du kannst URI::Find benutzen, um URLs aus einem beliebigen Text-Dokument zu filtern.

Weniger komplette Lösungen, die Reguläre Ausdrücke benutzen, können viel Laufzeit sparen, wenn Du weißt, dass die Eingabe einfach ist. Eine Lösung von Tom Christians läuft 100x schnelle als die meisten Modul-basierten Ansätze, filtert aber nur die URLs von Ankern, bei denen das erste Attribut HREF ist und keine weiteren Attribute hat.

        #!/usr/bin/perl -n00
        # qxurl - tchrist@perl.com
        print "$2\n" while m{
                < \s*
                  A \s+ HREF \s* = \s* (["']) (.*?) \1
                \s* >
        }gsix;

Wie kann ich eine Datei von der Maschine des Benutzers herunterladen? Wie kann ich eine Datei auf einer anderen Maschine öffnen?

In diesem Fall bedeutet ``herunterladen'' die Datei-Upload-Funktion von HTML-Formularen zu benutzen. Du erlaubst dem Webuser eine Datei anzugeben, die zu Deinem Webserver geschickt werden soll. Für Dich sieht es wie ein Download aus und für den Benutzer sieht es wie ein Upload aus. Egal wie Du es nennt, Du tust es mit etwas, das als mulitpart/form-data-Encoding bekannt ist. Das CGI.pm Modul (das als Teil der Standardbibliotheken mit Perl mitgeliefert wird) unterstützt das in der start_multipart_form()-Methode, die nicht das gleiche wie die startform()-Methode ist.

Für Code-Beispiele und Details schau Dir den Abschnitt über Datei-Uploads in der CGI.pm- Dokumentation an.

Wie mache ich ein HTML Pop-Up-Menü mit Perl?

(beigetragen von brian d foy)

Das CGI.pm-Module (das mit Perl mitgeliefert wird) hat Funktionen, um die HTML-Formularfelder zu erzeugen. Schau Dir die CGI.pm-Dokumentation für mehr Beispiele an.

        use CGI qw/:standard/;
        print header,
                start_html('Favorite Animals'),
                start_form,
                        "What's your favorite animal? ",
                popup_menu(
                        -name   => 'animal',
                        -values => [ qw( Llama Alpaca Camel Ram ) ]
                        ),
                submit,
                end_form,
                end_html;

Wie rufe ich eine HTML-Datei ab?

(beigetragen von brian d foy)

Benutze die libwww-perl Distribution. Das Modul LWP::Simple kann Web-Ressourcen holen und Dir deren Inhalt als String zurückgeben:

        use LWP::Simple qw(get);
        my $html = get( "http://www.example.com/index.html"; );

Es kann auch die Ressource direkt in einer Datei speichern:

        use LWP::Simple qw(getstore);
        getstore( "http://www.example.com/index.html";, "foo.html" );

Wenn Du etwas komplizierteres machen musst, kannst Du das Modul LWP::UserAgent benutzen, um einen eigenen User-Agent (z.B. Browser) zu erstellen um die Aufgabe zu erledigen. Wenn Du einen interaktiven Webbrowser simulieren willst, kannst Du das Modul WWW::Mechanize verwenden.

Wie kann ich HTML-Formulare automatisiert abschicken?

Wenn Du etwas komplexes machen willst, wie z.B. durch viele Seiten und Formulare oder eine Webseite zu bewegen, kannst Du WWW::Mechanize verwenden. Schau Dir dessen Dokumentation für alle Details an.

Wenn Du Werte mit der GET-Methode abschicken willst, erstelle eine URL und kodiere das Formular mit der query_form-Methode:

        use LWP::Simple;
        use URI::URL;
        my $url = url('http://www.perl.com/cgi-bin/cpan_mod');
        $url->query_form(module => 'DB_File', readme => 1);
        $content = get($url);

Wenn Du die POST-Methode benutzt, erzeuge Dir einen eigenen User-Agent und kodiere den Inhalt entsprechend.

        use HTTP::Request::Common qw(POST);
        use LWP::UserAgent;
        $ua = LWP::UserAgent->new();
        my $req = POST 'http://www.perl.com/cgi-bin/cpan_mod',
                                   [ module => 'DB_File', readme => 1 ];
        $content = $ua->request($req)->as_string;

Wie kann ich diese %-Kodierung im Web dekodieren oder erzeugen?

(beigetragen von brian d foy)

Die % Kodierungen behandeln resvierte Zeichen in URIs, wie es im RFC 2396 Abschnitt 2 beschrieben ist. Diese Kodierung ersetzt das reservierte Zeichen mit der Hexadezimalen Schreibweise der Nummer des Zeiches in der US-ASCII-Tabelle. Zum Beispiel wird der Doppelpunkt, :, zu %3A.

In CGI-Skripten, brauchst Du dich um das Dekodieren der URIs kümmern, wenn Du CGI.pm benutzt. Du solltest Dich nicht selbst um die Behandlung der URI kümmern, weder in die eine Richtung noch in die andere.

Wenn Du einen String selbst kodieren musst, denke daran, dass Du niemals versuchen solltest eine bereits zusammengestellte URI zu kodieren. Du musst die Komponenten einzeln escapen und danach zusammenfügen. Um einen String zu kodieren, kannst Du das URI::Escape Modul verwenden. Die uri_escape Funktion liefert den geschützten String zurück:

        my $original = "Colon : Hash # Percent %";
        my $escaped = uri_escape( $original );
        print "$escaped\n"; # 'Colon%20%3A%20Hash%20%23%20Percent%20%25'

Benutze die uri_unescape Funktion, um den String zu dekodieren:

        my $unescaped = uri_unescape( $escaped );
        print $unescaped; # zurueck beim Original

Wenn Du es selbst machen möchtest, brauchst Du nur einfach die reservierten Zeichen mit ihrer Kodierung zu ersetzen. Eine globale Ersetzung ist ein Weg, das zu tun:

        # encode
        $string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%0x", ord $1 /eg;
        #decode
        $string =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;

Wie kann ich auf eine andere Seite weiterleiten?

Lege die komplette URL des Ziels fest (selbst wenn es auf dem gleichen Server ist). Dies ist eine der zwei unterschiedlichen Arten von CGI ``Location:'' Antworten, die in der CGI-Spezifikation für ein ``Parsed Headers'' Skript definiert sind. Die andere Art (ein absoluter URL-Pfad) wird intern auf dem Server aufgelöst, ohne jede HTTP-Weiterleitung. Die CGI-Spezifikation erlaubt in keinem dieser Fälle relative URLs.

Die Verwendung von CGI.pm ist dringend empfohlen. Dieses Beispiel zeigt die Weiterleitung mit einer kompletten URL. Diese Weiterleitung wird durch den Webbrowser gehandhabt.

        use CGI qw/:standard/;
        my $url = 'http://www.cpan.org/';
        print redirect($url);

Dieses Beispiel zeigt die Weiterleitung mit einem absoluten URL-Pfad. Diese Weiterleitung wird durch den Webbrowser gehandhabt.

        my $url = '/CPAN/index.html';
        print redirect($url);

Aber direkt gecodet, könnte es wie folgt aussehen (das abschließende ``\n'' ist zur Übersichtlichkeit extra angegeben) und benutzt entweder eine komplette URL oder einen absoluten URL-Pfad.

        print "Location: $url\n";   # CGI Antwort-Header
        print "\n";                 # Ende der Header

Wie kann ich ein Passwort auf meiner Webseite einbauen?

Um Authentifizierung für Deinen Webserver einzuschalten, musst Du Deinen Webserver konfigurieren. Die Konfiguration ist verschieden bei den unterschiedlichen Typen von Webservern--Apache macht es anders als iPlanet, das es anders als der IIS macht. Prüfe Deine Webserver-Dokumentation für die Details Deines entsprechenden Servers.

Wie kann ich meine .htpasswd und .htgroup Dateien mit Perl bearbeiten?

Die Module HTTPD::UserAdmin und HTTPD::GroupAdmin bieten eine konsistente OO Schnittstelle für diese Dateien, egal wie sie gespeichert sind. Datenbanken können Text, DBM, Berkeley DB oder irgendeine Datenbank mit einem DBI-kompatiblen Treiber sein. HTTPD::UserAdmin unterstützt Dateien, die für das ``Basic'' und ``Digest'' Authentifizierungs-Schema verwendet werden. Hier ein Beispiel:

        use HTTPD::UserAdmin ();
        HTTPD::UserAdmin
          ->new(DB => "/foo/.htpasswd")
          ->add($username => $password);

Wie kann ich sicherstellen, dass Benutzer keine Daten eingeben können, die mein CGI-Skript böse Sachen machen lassen?

Schau Dir die Sicherheits-Referenzen an, die in der CGI Meta FAQ aufgeführt sind

        http://www.perl.org/CGI_MetaFAQ.html

Wie kann ich einen Mail-Header parsen?

Für eine ``quick-and-dirty'' Lösung, probiere dies Lösung aus, die aus perlfunc/split abgeleitet ist:

        $/ = '';
        $header = <MSG>;
        $header =~ s/\n\s+/ /g;  # merge continuation lines
        %head = ( UNIX_FROM_LINE, split /^([-\w]+):\s*/m, $header );

Diese Lösung funktioniert nicht richtig, wenn Du z.B. versuchst alle ``Received''-Zeilen zu behalten. Ein besserer Ansatz ist es, das Mail::Header-Module vom CPAN (Teil des MailTools Pakets) zu benutzen.

Wie dekodiere ich ein CGI-Formular?

(beigetragen von brian d foy)

Verwende das CGI.pm-Modul, das mit Perl mitgeliefert wird. Es is schnell, es ist einfach und es macht wirklich eine ganze Menge um sicherzustellen, dass die Dinge korrekt funktionieren. Es handhabt GET-, POST- und HEAD-Anfragen, multipart Formulare, Felder mit mehreren Werten, Query-Strings, Nachrichtentext Kombinationen und viele andere Dinge, über Dir Du nicht nachdenken willst.

Es geht nicht viel einfacher: Das CGI.pm Modul parst automatisch die Eingabe und macht jeden Wert über die param()-Funktion verfügbar.

        use CGI qw(:standard);
        my $total = param( 'price' ) + param( 'shipping' );
        my @items = param( 'item' ); # multiple values, same field name

Wenn Du einen Objektorientierten Ansatz möchtest, kann CGI.pm das auch.

        use CGI;
        my $cgi = CGI->new();
        my $total = $cgi->param( 'price' ) + $cgi->param( 'shipping' );
        my @items = $cgi->param( 'item' );

Vielleicht möchtest Du auch CGI::Minimal testen, das eine leichtgewichtige Version der gleichen Sache ist. Andere CGI::* Module auf CPAN können für Dich auch besser funktionieren.

Viele Leute versuchen ihren eigenen Dekoder zu schreiben (oder einen von einem anderen Programm kopieren) und laufen dann in eine der vielen ``Fallen'' dieser Aufgabe. Es ist viel einfacher und weniger mühevoll, CGI.pm zu verwenden.

Wie kann ich eine gültige Mail-Adresse prüfen?

(teilweise von Aaron Sherman beigetragen)

Das ist keine so einfache Frage wie sie klingt. Es gibt zwei Teile:

a) Wie überprüfe ich, dass eine Mail-Adresse korrekt formatiert ist?

b) Wie überprüfe ich, dass eine Mail-Adresse auf einen gültigen Empfänger verweist?

Ohne eine Mail an die Adresse zu schicken und zu schauen, ob ein Mensch auf der anderen Seite Dir antwortet, kannst Du Teil b nicht abschließend beantworten, aber entweder das Email::Valid- oder das RFC::RFC822::Address-Modul können sowohl Teil a als auch Teil <b> machen, soweit es in real-time möglich ist.

Wenn Du nur Teil a mit einem einfach Regulären Ausdruck prüfen möchtest, um zu sehen, dass eine Adresse nach dem Mail-Header-Standard gültig ist, kannst Du Probleme bekommen, weil es zustellbare Adresse gibt, die nicht RFC-2822-konform sind (der aktuellst Mail-Header-Standard) und nicht-zustellbare Adressen, die konform sind. Wie auch immer, das Folgende wird für gültige RFC-2822-Adressen passen, die keine Kommentare, ``folding whitespaces'' oder irgendwelche anderen obsoleten oder unwesentlichen Elemente haben. Das matcht nur die Adresse selbst:

        my $atom       = qr{[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+};
        my $dot_atom   = qr{$atom(?:\.$atom)*};
        my $quoted     = qr{"(?:\\[^\r\n]|[^\\"])*"};
        my $local      = qr{(?:$dot_atom|$quoted)};
        my $quotedpair = qr{\\[\x00-\x09\x0B-\x0c\x0e-\x7e]};
        my $domain_lit = qr{\[(?:$quotedpair|[\x21-\x5a\x5e-\x7e])*\]};
        my $domain     = qr{(?:$dot_atom|$domain_lit)};
        my $addr_spec  = qr{$local\@$domain};

Überprüfe eine Adresse einfach mit /^${addr_spec}$/, um zu sehen, ob sie der RFC2822-Spezifikation folgt. Wie auch immer, weil es unmöglich ist, sicher zu sein, dass eine solche korrekt geformte Adresse der richtige Weg ist eine bestimmte Person zu erreichen oder überhaupt mit einer Mailbox verbunden ist, musst Du sehr vorsichtig sein, wie Du das nutzt.

Unser bester Hinweis für die Überprüfung der Mail-Adresse einer Person, ist, sie ihre Adresse zweimal eingeben zu lassen, so wie Du es normalerweise machst, um ein Passwort zu ändern. Das merzt normalerweise Tippfehler aus. Wenn beide Versionen gleich sind, schicke eine Mail mit einer persönlichen Nachricht an diese Adresse. Wenn Du eine Nachricht zurückbekommst und sie Deinen Anweisungen gefolgt sind, kannst Du einigermaßen sicher sein, dass die Adresse real ist.

Eine verwandte Strategie, die weniger anfällig für Missbrauch ist, ist, ihnen eine PIN (Persönliche ID Nummer) zu geben. Speichere die Adresse und die PIN (am Besten ist sie eine zufällige Nummer) für die spätere Bearbeitung. In der Nachricht, die Du ihnen schickst, forderst Du sie auf, die PIN in ihrer Antwort anzugeben. Wenn die Mail aber zurückkommt oder in einer Abwesenheitsnotiz enthalten ist, wird die PIN auch vorhanden sein. Also ist es das Beste, eine leicht veränderte Version der PIN zurück zu mailen, z.B. mit den Zeichen in umgekehrter Reihenfolge, oder zu jeder Zahl eins hinzuaddiert oder subtrahiert, etc.

Wie dekodiere ich einen MIME/BASE64 String?

Das MIME-Base64 Paket (auf CPAN verfügbar) handhabt das - genauso wie das MIME/QP-Encoding. BASE64 zu dekodieren wird so einfach wie:

        use MIME::Base64;
        $decoded = decode_base64($encoded);

Das MIME-Tools Pakete (auf CPAN verfügbar) unterstützt das Herausziehen und dekodieren von BASE64-kodierten Anhängen und Inhalten direkt aus Mail-Nachrichten.

Wenn der zu dekodierende String kurz ist (kürzer als 84 Bytes) ist ein direkterer Ansatz, das ``u'' Format der unpack()-Funktion nach einer kleineren Transliteration zu verwenden:

        tr#A-Za-z0-9+/##cd;                   # loesche nicht-BASE64 Zeichen
        tr#A-Za-z0-9+/# -_#;                  # konvertiere in uuencoded Format
        $len = pack("c", 32 + 0.75*length);   # Berechne Längen-Byte
        print unpack("u", $len . $_);         # uudecode und Ausgabe

Wie kann ich die Mail-Adresse des Users zurückgeben?

Auf Systemen, die getpwuid, die $< Variable und das Sys::Hostname Modul (das Teil der Standard perl Distribution ist) unterstützen, kannst Du wahrscheinlich versuchen, so etwas zu benutzen:

        use Sys::Hostname;
        $address = sprintf('%s@%s', scalar getpwuid($<), hostname);

Unternehmensrichtlinien bezüglich Mail-Adressen können dazu führen, dass dies Adressen generiert, die das Mailsystem des Unternehmens nicht akzeptiert. Also solltest Du nach der Mail-Adresse eines Benutzers fragen, wenn das von Bedeutung ist. Weiterhin sind nicht alle Systeme, auf denen Perl läuft, so mitteilsam bei solchen Informationen wie Unix.

Das Mail::Util Modul von CPAN (Teil des MailTools Pakets) bietet eine mailaddress() Funktion, die versucht, die Mail-Adresse des Benutzers zu erraten. Es macht einen intelligenteren Rateversuch als der Code oben, indem es Informationen benutzt, die bei der Installation des Moduls gegeben wurden - aber es kann immer noch falsch sein. Noch einmal, der beste Weg ist es oft, einfach den Benutzer zu fragen.

Wie verschicke ich Mails?

Verwende direkt das sendmail Programm:

        open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")
                or die "Can't fork for sendmail: $!\n";
        print SENDMAIL <<"EOF";
        From: User Originating Mail <me\@host>
        To: Final Destination <you\@otherhost>
        Subject: A relevant subject line
        Body of the message goes here after the blank line
        in as many lines as you like.
        EOF
        close(SENDMAIL)     or warn "sendmail didn't close nicely";

Die -oi-Option unterdrückt, dass sendmail eine Zeile, die nur aus einem einzlenen Punkt besteht, als ``Ende der Nachricht'' interpretiert. Die -t Option sagt, dass die Header benutzt werden sollen, um zu entscheiden, an wen die Nachricht geschickt werden soll. Und -odq sagt, dass die Nachricht in die Queue geschoben werden soll. Diese letzte Option bedeutet, dass Deine Nachrichte nicht unmittelbar ausgeliefert wird, also lasse es weg, wenn Du eine unmittelbare Zustellung willst.

Alternativ, weniger bequeme Ansätze beinhalten den direkten Aufruf von mail (manchmal mailx genannt) oder einfach Port 25 zu öffnen, um eine vertrauliche Konversation zwischen Dir und dem entfernten SMTP-Daemon, wahrscheinlich sendmail, zu haben.

Oder Du könntest das CPAN-Modul Mail::Mailer verwenden:

        use Mail::Mailer;
        $mailer = Mail::Mailer->new();
        $mailer->open({ From    => $from_address,
                                To      => $to_address,
                                Subject => $subject,
                        })
                or die "Can't open: $!\n";
        print $mailer $body;
        $mailer->close();

Das Mail::Internet Modul verwendet Net::SMTP, das weniger Unix-bezogen ist als Mail::Mail, aber weniger zuverlässiger ist. Vermeide nackte SMTP-Kommandos. Es gibt viele Gründe, einen Mail Transport Agent wie sendmail zu verwenden. Das schließt das Bilden von Queues, MX-Einträge und Sicherheit ein.

Wie kann ich MIME für einen Anhang an einer Mail benutzen?

Diese Antwort ist direkt aus der Dokumentation von MIME::Lite herausgezogen. Erzeugen einer Multipart-Nachricht (z.B. eine mit Anhängen).

        use MIME::Lite;
        ### Create a new multipart message:
        $msg = MIME::Lite->new(
                                 From    =>'me@myhost.com',
                                 To      =>'you@yourhost.com',
                                 Cc      =>'some@other.com, some@more.com',
                                 Subject =>'A message with 2 parts...',
                                 Type    =>'multipart/mixed'
                                 );
        ### Add parts (each "attach" has same arguments as "new"):
        $msg->attach(Type     =>'TEXT',
                                 Data     =>"Here's the GIF file you wanted"
                                 );
        $msg->attach(Type     =>'image/gif',
                                 Path     =>'aaa000123.gif',
                                 Filename =>'logo.gif'
                                 );
        $text = $msg->as_string;

MIME::Lite beinhaltet auch eine Methode, um diese Dinge zu senden.

        $msg->send;

Das benutzt standardmäßig sendmail, kann aber so angepasst werdn, dass es SMTP via the Net::SMTP manpage verwendet.

Wie lese ich Mails?

Auch wenn Du das Mail::Folder Modul von CPAN (Teil des MailFolder Pakets) oder das Mail::Internet Modul von CPAN (Teil des MailTools Pakets) benutzen kannst, ist ein Modul oft zu viel. Hier ist ein Mail-Sortierer.

        #!/usr/bin/perl
        my(@msgs, @sub);
        my $msgno = -1;
        $/ = '';                    # paragraph reads
        while (<>) {
                if (/^From /m) {
                        /^Subject:\s*(?:Re:\s*)*(.*)/mi;
                        $sub[++$msgno] = lc($1) || '';
                }
                $msgs[$msgno] .= $_;
        }
        for my $i (sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msgs)) {
                print $msgs[$i];
        }

Oder mehr kurz und bündig,

        #!/usr/bin/perl -n00
        # bysub2 - awkish sort-by-subject
        BEGIN { $msgno = -1 }
        $sub[++$msgno] = (/^Subject:\s*(?:Re:\s*)*(.*)/mi)[0] if /^From/m;
        $msg[$msgno] .= $_;
        END { print @msg[ sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msg) ] }

Wie kann ich meinen Hostnamen, Domainnamen oder IP-Adresse herausfinden?

(beigetragen von brian d foy)

Das Net::Domain Modul, das Teil der Standard-Distribution seit perl5.7.3 ist, kann Dir den vollqualifizierten Domain-Namen (FQDN), den Hostnamen oder den Domain-Namen holen.

        use Net::Domain qw(hostname hostfqdn hostdomain);
        my $host = hostfqdn();

Das Sys::Hostname Modul, in der Standard-Distribution seit perl5.6, kann cu den Hostnamen holen.

        use Sys::Hostname;
        $host = hostname();

Um die IP-Adresse zu bekommen, kannst Du die gethostbyname Built-in Funktion verwenden und den Namen in eine Nummer umwandeln. Um diese Nummer in die Oktett-Form mit Punkten (a.b.c.d) zu bekommen, die die meisten Leute erwarten, benutze die inet_ntoa Funktion aus dem Socket Modul, das ebenfalls mit perl mitkommt.

        use Socket;
        my $address = inet_ntoa(
                scalar gethostbyname( $host || 'localhost' )
                );

Wie kann ich einen News-Artikel oder die aktive Newsgroup holen?

Benutze das Net::NNTP- oder News::NNTPClient-Modul, die es beide auf dem CPAN gibt. Das macht Aufgabe wie das holen der Newsgroup-Liste so einfach wie

        perl -MNews::NNTPClient
          -e 'print News::NNTPClient->new->list("newsgroups")'

Wie kann ich eine Datei per FTP holen/hochladen?

LWP::Simple (auf dem CPAN verfügbar) kann Dateien holen aber nicht hochladen. Net::FTP (ebenfalls auf dem CPAN verfügbar) is komplexer kann aber sowohl Dateien hochladen als auch holen.

Wie kann ich RPC in Perl verwenden?

(beigetragen von brian d foy)

Benutze eines der RPC-Module, die Du auf CPAN finden kannst ( http://search.cpan.org/search?query=RPC&mode=all ).


REVISION

Revision: $Revision$

Datum: $Date$

Für Details über Versionskontrolle und Verfügbarkeit siehe perlfaq.


AUTOR UND COPYRIGHT

Copyright (c) 1997-2009 Tom Christiansen, Nathan Torkington und andere Autoren wie genannt. Alle Rechte vorbehalten.

Diese Dokument ist frei; Du kannst es unter den gleichen Bedingungen wie Perl selbst weiterverteilen und/oder verändern.

Unabhängig von der Verteilung, sind alle Code-Beispiele Gemeingut. Dir wird erlaubt und du wirst ermutigt, sie und beliebige davon abgeleitete in deinen Programmen zum Spaß oder für Profit zu verwenden. Ein einfacher Kommentar im Code, der die FAQ würdigt, wäre nett, ist aber nicht erforderlich.

Übersetzung von Renée Bäcker