Skip to content

9. Die Netzwerkfunktionen von PHP

Wir befassen uns nun mit den Netzwerkfunktionen von PHP, die uns die Programmierung von TCP / IP (Transfer Control Protocol / Internet Protocol) ermöglichen.

9.1. Den Namen oder die Adresse IP eines Rechners im Internet (inet_01) abrufen


<?php

// Funktionen: Maschinenname <--> Adresse IP der Maschine
ini_set("display_errors", "off");
// Konstanten
$HOTES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "localhost", "", "xx");
// Adressen IP der Maschinen von $HOTES
for ($i = 0; $i < count($HOTES); $i++) {
  getIPandName($HOTES[$i]);
}
// Ende
exit;

//------------------------------------------------
function getIPandName($nomMachine) {
//$nomMachine: Name des Rechners, dessen Adresse IP benötigt wird
// nomMachine-->Adresse IP
  $ip = gethostbyname($nomMachine);
  if ($ip != $nomMachine) {
    print "ip[$nomMachine]=$ip\n";
// Adresse IP --> nomMachine
    $name = gethostbyaddr($ip);
    if ($name != $ip) {
      print "name[$ip]=$name\n";
    } else {
      print "Erreur, machine[$ip] non trouvée\n";
    }
  } else {
    print "Erreur, machine[$nomMachine] non trouvée\n";
  }
}

Ergebnisse:

ip[istia.univ-angers.fr]=193.49.146.171
name[193.49.146.171]=istia.istia.univ-angers.fr
ip[www.univ-angers.fr]=193.49.144.40
name[193.49.144.40]=ametys-fo.univ-angers.fr
ip[www.ibm.com]=129.42.56.216
Erreur, machine[129.42.56.216] non trouvée
ip[localhost]=127.0.0.1
name[127.0.0.1]=localhost127.0.0.1
ip[]=192.168.1.11
name[192.168.1.11]=st-PC.home
Erreur, machine[xx] non trouvée

Kommentare

  • Zeile 4: Es wird festgelegt, dass Laufzeitfehler nicht angezeigt werden sollen.

Die Netzwerkfunktionen von PHP werden in der Funktion getIpandName in Zeile 15 verwendet.

  • Zeile 18: Mit der Funktion gethostbyname($nom) wird die Adresse IP „ip3.ip2.ip1.ip0“ des Rechners mit dem Namen $nom ermittelt. Wenn der Rechner $nom nicht existiert, gibt die Funktion $nom als Ergebnis zurück.
  • Zeile 22: Die Funktion gethostbyaddr($ip) ermittelt den Namen des Rechners mit der Adresse $ip in der Form „ip3.ip2.ip1.ip0“. Wenn der Rechner $ip nicht existiert, gibt die Funktion $ip als Ergebnis zurück.

9.2. Ein Webclient ( inet_02)

Ein Skript, mit dem der Inhalt der Startseite einer Website abgerufen werden kann.


<?php

// Fehlerbehandlung
ini_set("display_errors","off");
// Text abrufen HTML von URL
// Liste der Websites
$SITES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "xx");
// Auslesen der Indexseiten der Websites aus der Tabelle $SITES
for ($i = 0; $i < count($SITES); $i++) {
// Auslesen der Indexseite der Website $SITES[$i]
  $résultat = getIndex($SITES[$i]);
// Anzeige des Ergebnisses
  print "$résultat\n";
}//für
// Ende
exit;

//-----------------------------------------------------------------------
function getIndex($site) {
// liest die Datei URL $site/ und speichert sie in der Datei $site.html
// Erstellung der Datei $site.html
  $html = fopen("$site.html", "w");
  if (!$html)
    return "Erreur lors de la création du fichier $site.html";

// Öffnen einer Verbindung auf Port 80 von $site
  $connexion = fsockopen($site, 80);
// Rückkehr im Fehlerfall
  if (!$connexion)
    return "Echec de la connexion au site ($site,80) : $erreur";
// $connexion stellt einen bidirektionalen Kommunikationsfluss dar
// zwischen dem Client (diesem Programm) und dem angerufenen Webserver
// Dieser Kanal wird für den Austausch von Befehlen und Informationen genutzt
// Das Kommunikationsprotokoll lautet HTTP
// Der Client sendet den Befehl „get“, um die URL anzufordern /
// „get“-Syntax: URL HTTP/1.0
// Die Header des Protokolls HTTP müssen mit einer Leerzeile enden
  fputs($connexion, "GET / HTTP/1.0\n\n");
// Der Server antwortet nun auf dem Kanal $connexion. Er sendet alle
// diese Daten senden und anschließend den Kanal schließen. Der Client liest also alles, was von $connexion
// bis zum Schließen des Kanals
  while ($ligne = fgets($connexion, 1000))
    fputs($html, $ligne);
// schließlich schließt der Client seinerseits die Verbindung
  fclose($connexion);
// Schließen der Datei $html
  fclose($html);
// Rückgabe
  return "Transfert réussi de la page index du site $site";
}

Ergebnisse: Beispielsweise die für die Website [www.ibm.com] empfangene Datei:

HTTP/1.1 302 Found
Date: Wed, 08 Jun 2011 15:43:56 GMT
Server: IBM_HTTP_Server
Content-Type: text/html
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Location: http://www.ibm.com/us/en/
Content-Length: 209
Kp-eeAlive: timeout=10, max=14
Connection: Keep-Alive

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://www.ibm.com/us/en/">here</a>.</p>
</body></html>
  • Die Zeilen 1–11 sind die HTTP-Header der Serverantwort
  • Zeile 1: Der Server fordert den Client auf, sich zu der in Zeile 8 angegebenen Adresse URL weiterzuleiten
  • Zeile 2: Datum und Uhrzeit der Antwort
  • Zeile 3: Identität des Webservers
  • Zeile 4: Vom Server gesendeter Inhalt. Hier eine Seite mit der ID HTML, die in Zeile 13 beginnt
  • Zeile 12: Die leere Zeile, die die Header HTTP abschließt
  • Zeilen 13–19: die vom Webserver gesendete Seite HTML.

Kommentare zum Code:

  • Zeile 7: Die Liste der URLs der Websites, deren Startseite abgerufen werden soll. Diese wird in der Textdatei [nomsite.html] gespeichert.
  • Zeile 11: Die Funktion getIndex führt die Aufgabe aus
  • Zeile 19: Die Funktion getIndex($site) lädt die Startseite (oder Indexseite) der Website $site herunter und speichert sie in der Textdatei $site.html.
  • Zeile 27: Mit der Funktion fsockopen($site,$port) wird eine Verbindung zu einem Dienst TCP hergestellt / IP herzustellen, der auf dem Port $port des Rechners $site läuft. Sobald die Client-Server-Verbindung hergestellt ist, tauschen zahlreiche Dienste TCP / IP Textzeilen aus. Dies ist hier beim Protokoll HTTP (HyperText Transfer Protocol) der Fall. Der vom Server an den Client gesendete Datenstrom kann dann wie eine Textdatei verarbeitet werden. Gleiches gilt für den vom Client an den Server gesendeten Datenstrom.
  • Zeile 38: Die Funktion fputs ermöglicht es dem Client, Daten an den Server zu senden. Die hier gesendete Textzeile hat folgende Bedeutung: „Ich möchte (GET) die Startseite (/) der Website, mit der ich verbunden bin. Ich arbeite mit dem Protokoll HTTP, Version 1.0“. Die aktuelle Version dieses Protokolls ist 1.1.
  • Zeile 42: Die Textzeilen der Serverantwort können zeilenweise mit einer Schleife gelesen und in der Textdatei gespeichert werden. Sobald der Webserver die angeforderte Seite gesendet hat, schließt er die Verbindung zum Client. Auf der Client-Seite wird dies als Dateiende erkannt.

9.3. Ein SMTP-Client (inet_03)

Unter den Protokollen TCP / IP ist SMTP (SendMail Transfer Protocol) das Kommunikationsprotokoll des Nachrichtendienstes.

Hinweise:

  • Auf einem Windows-Rechner mit Antivirenprogramm verhindert dieses wahrscheinlich, dass das Skript PHP eine Verbindung zum Port 25 eines SMTP-Servers herstellt. In diesem Fall muss das Antivirenprogramm deaktiviert werden. Für McAfee kann man beispielsweise wie folgt vorgehen:
  • in [1], die Konsole VirusScan aktivieren
  • bei [2] wird der Dienst [Protection lors de l'accès] beendet
  • bei [3] ist er gestoppt

Das Skript:


<?php

// Client SMTP (SendMail-Übertragungsprotokoll) zum Senden einer Nachricht
// Die Informationen werden aus einer Datei $INFOS entnommen, die folgende Zeilen enthält
// Zeile 1: SMTP, Absender, Empfänger
// folgende Zeilen: der Text der Nachricht
// Absender: E-Mail-Adresse des Absenders
// Empfänger: E-Mail-Adresse des Empfängers
// SMTP: Name des zu verwendenden SMTP-Servers
// Kommunikationsprotokoll SMTP Client-Server
// -> Der Client verbindet sich über Port 25 mit dem SMTP-Server
// <- Der Server sendet ihm eine Willkommensnachricht
// -> Der Client sendet den Befehl EHLO: Name seines Rechners
// <- Der Server antwortet mit OK oder nicht
// -> Der Client sendet den Befehl „mail from: <Absender>“
// <- Server antwortet mit OK oder nicht
// -> Der Client sendet den Befehl „rcpt to: <Empfänger>“
// <- Server antwortet mit OK oder nicht
// -> Der Client sendet den Befehl „data“
// <- Server antwortet mit OK oder nicht
// -> Der Client sendet alle Zeilen seiner Nachricht und schließt mit einer Zeile ab, die das
// einzigen Zeichen.
// <- Der Server antwortet mit OK oder nicht
// -> Der Client sendet den Befehl „quit“
// <- Der Server antwortet mit „OK“ oder nicht
// Die Antworten des Servers haben die Form „xxx Text“, wobei „xxx“ eine dreistellige Zahl ist. Jede Zahl „xxx“ >= 500
// deutet auf einen Fehler hin. Die Antwort kann mehrere Zeilen umfassen, die alle mit xxx beginnen, außer der letzten
// in der Form xxx(Leerzeichen)
// Die ausgetauschten Textzeilen müssen mit den Zeichen RC(#13) und LF(#10) enden

// Daten
$INFOS = "mail.txt"; // die Parameter für den E-Mail-Versand
// Die E-Mail-Parameter werden abgerufen
list($erreur, $smtpServer, $expéditeur, $destinataire, $message) = getInfos($INFOS);
// Fehler?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire]\n";
// E-Mail-Versand im ausführlichen Modus
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, 1);
print "Résultat de l'envoi : $résultat\n";
// Ende
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
// gibt die Informationen ($smtp,$expéditeur,$destinataire,$message) aus der Textdatei $fichier
// Zeile 1: SMTP, Absender, Empfänger
// folgende Zeilen: der Text der Nachricht

// Öffnen der Datei „$fichier“
  $infos = fopen($fichier, "r");
// Existiert die Datei $fichier?
  if (!$infos)
    return array("Le fichier $fichier n'a pu être ouvert en lecture");
// Lesen der ersten Zeile
  $ligne = fgets($infos, 1000);
// Entfernen des Zeilenendezeichens
  $ligne = cutNewLineChar($ligne);
// Abruf der Felder smtp, Absender, Empfänger
  $champs = explode(",", $ligne);
// Ist die Anzahl der Felder korrekt?
  if (count($champs) != 3)
    return "La ligne 1 du fichier $fichier (serveur smtp, expéditeur, destinataire) a un
nombre de champs incorrect";
// „Verarbeitung“ der abgerufenen Informationen
  for ($i = 0; $i < count($champs); $i++)
    $champs[$i] = trim($champs[$i]);
// Abruf der Felder
  list($smtpServer, $expéditeur, $destinataire) = $champs;
// Nachricht lesen
  $message = "";
  while ($ligne = fgets($infos, 1000))
    $message.=$ligne;
  fclose($infos);
// Rückgabe
  return array("", $smtpServer, $expéditeur, $destinataire, $message);
}

//-----------------------------------------------------------------------

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $verbose) {
// sendet $message an den SMTP-Server $smtpserver im Namen von $expéditeur
// für $destinataire. Wenn $verbose=1 ist, wird der Austausch zwischen Client und Server nachverfolgt
// wird der Name des Clients abgerufen
  $client = gethostbyaddr(gethostbyname(""));
// Aufbau einer Verbindung auf Port 25 von $smtpServer
  $connexion = fsockopen($smtpServer, 25);
// Rückgabe bei Fehler
  if (!$connexion)
    return "Echec de la connexion au site ($smtpServer,25)";
// $connexion stellt einen bidirektionalen Kommunikationsfluss dar
// zwischen dem Client (diesem Programm) und dem kontaktierten SMTP-Server
// Dieser Kanal wird für den Austausch von Befehlen und Informationen genutzt

// Nach dem Verbindungsaufbau sendet der Server eine Begrüßungsnachricht, die gelesen wird
  $erreur = sendCommand($connexion, "", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Befehl „ehlo“:
  $erreur = sendCommand($connexion, "EHLO $client", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Befehl „mail from“:
  $erreur = sendCommand($connexion, "MAIL FROM: <$expéditeur>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Befehl „rcpt to“:
  $erreur = sendCommand($connexion, "RCPT TO: <$destinataire>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Befehl „data“
  $erreur = sendCommand($connexion, "DATA", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Vorbereitung der zu versendenden Nachricht
  // sie muss folgende Zeilen enthalten
  // Von: Absender
  // An: Empfänger
  // Leere Zeile
  // Nachricht
  // .
  $data = "From: $expéditeur\r\nTo: $destinataire\r\n$message\r\n.\r\n";
  $erreur = sendCommand($connexion, $data, $verbose, 0);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Befehl „quit“
  $erreur = sendCommand($connexion, "QUIT", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// Ende
  fclose($connexion);
  return "Message envoyé";
}

// --------------------------------------------------------------------------

function sendCommand($connexion, $commande, $verbose, $withRCLF) {
// sendet $commande an den Kanal $connexion
// Ausführlicher Modus, wenn $verbose=1
// Wenn $withRCLF=1, fügt die Sequenz RCLF zum Austausch hinzu

// Daten
  if ($withRCLF)
    $RCLF = "\r\n"; else
    $RCLF="";

// Befehl senden, wenn $commande nicht leer ist
  if ($commande) {
    fputs($connexion, "$commande$RCLF");

// eventuelles Echo
    if ($verbose)
      affiche($commande, 1);
  }//if

// Antwort lesen
  $réponse = fgets($connexion, 1000);

// eventuelles Echo
  if ($verbose)
    affiche($réponse, 2);

// Fehlercode abrufen
  $codeErreur = substr($réponse, 0, 3);

// Letzte Zeile der Antwort?
  while (substr($réponse, 3, 1) == "-") {

     // Antwort lesen
    $réponse = fgets($connexion, 1000);

     // eventuelles Echo
    if ($verbose)
      affiche($réponse, 2);
  }//while
// Antwort abgeschlossen

// Vom Server zurückgegebenen Fehler?
  if ($codeErreur >= 500)
    return substr($réponse, 4);

// Rückgabe ohne Fehler
  return "";
}

// --------------------------------------------------------------------------

function affiche($échange, $sens) {
// zeigt $échange auf dem Bildschirm an
// wenn $sens=1, wird -->$echange angezeigt
// wenn $sens=2, zeigt es <-- $échange ohne die letzten beiden Zeichen an: RCLF
  switch ($sens) {
    case 1:
      print "--> [$échange]\n";
      return;
    case 2:
      $L = strlen($échange);
      print "<-- [" . substr($échange, 0, $L - 2) . "]\n";
      return;
  }//-Schalter
}

// --------------------------------------------------------------------------

function cutNewLinechar($ligne) {
// Das Zeilenendezeichen von $ligne wird entfernt, falls vorhanden
  ...
}

Die Datei infos.txt:

1
2
3
4
5
6
7
smtp.orange.fr, serge.tahe@univ-angers.fr , serge.tahe@istia.univ-angers.fr
Subject: test

ligne1
ligne2

ligne3
  • Zeile 1: [smtp.orange.fr] – der für den E-Mail-Versand verwendete Server, [serge.tahe@univ-angers.fr] – die Absenderadresse, [serge.tahe@istia.univ-angers.fr] – die Empfängeradresse
  • Zeile 2: Kopfzeilen der Nachricht. Hier gibt es nur eine, nämlich die Betreffzeile der Nachricht.
  • Zeile 3: Die leere Zeile beendet die Kopfzeilen der Nachricht
  • Zeilen 4–7: Der Text der Nachricht

Die Bildschirmausgabe:

Envoi du message [smtp.orange.fr,serge.tahe@univ-angers.fr,serge.tahe@univ-angers.fr]
<-- [220 mwinf5d05 ME ESMTP server ready]
--> [EHLO st-PC.home]
<-- [250-mwinf5d05 hello [2.1.22.82], pleased to meet you]
<-- [250-HELP]
<-- [250-AUTH LOGIN PLAIN]
<-- [250-SIZE 44000000]
<-- [250-ENHANCEDSTATUSCODES]
<-- [250-8BITMIME]
<-- [250 OK]
--> [MAIL FROM: <serge.tahe@univ-angers.fr>]
<-- [250 2.1.0 <serge.tahe@univ-angers.fr> sender ok]
--> [RCPT TO: <serge.tahe@univ-angers.fr>]
<-- [250 2.1.5 <serge.tahe@univ-angers.fr> recipient ok]
--> [DATA]
<-- [354 enter mail, end with "." on a line by itself]
--> [From: serge.tahe@univ-angers.fr
To: serge.tahe@univ-angers.fr
Subject: test

ligne1
ligne2
ligne3
.
]
<-- [250 2.0.0 Ag3i1h0051mFoG203g3ip1 mail accepted for delivery]
--> [QUIT]
<-- [221 2.0.0 mwinf5d05 ME closing connection]
Résultat de l'envoi : Message envoyé
  • Zeile 1: Meldung zur Ausführung des Skripts
  • Zeile 2: Erste Antwort des SMTP-Servers. Sie folgt auf die Verbindung des Clients mit Port 25 des SMTP-Servers. Die Antworten des Servers bestehen aus Zeilen der Form [xxx message] oder [xxx-message]. Die erste Syntax zeigt an, dass die Antwort abgeschlossen ist. xxx ist ein Ergebniscode. Ein Wert größer oder gleich 500 weist auf einen Fehler hin. Die zweite Syntax zeigt an, dass die Antwort noch nicht abgeschlossen ist und eine weitere Zeile folgt.
  • Zeile 2: Der SMTP-Server signalisiert, dass er bereit ist, Befehle zu empfangen
  • Zeile 3: Der Client sendet den Befehl [EHLO nomDeMachine], wobei nomDeMachine der Internetname des Rechners ist, auf dem der Client läuft
  • Zeilen 4–10: Antwort des SMTP-Servers
  • Zeile 11: Der Client sendet den Befehl [MAIL FROM: <expéditeur>], der die E-Mail-Adresse des Absenders angibt.
  • Zeile 12: Der SMTP-Server bestätigt, dass er diese Adresse akzeptiert. Er hätte sie ablehnen können, wenn die Syntax falsch gewesen wäre. Allerdings überprüft er nicht, ob die E-Mail-Adresse tatsächlich existiert.
  • Zeile 13: Der Client sendet den Befehl [RCPT TO: <destinataire>], der die E-Mail-Adresse des Empfängers der Nachricht angibt.
  • Zeile 14: Der SMTP-Server antwortet, dass er diese Adresse akzeptiert. Auch hier wird eine Syntaxprüfung durchgeführt.
  • Zeile 15: Der Client sendet den Befehl [DATA], der dem Benutzer signalisiert, dass die folgenden Zeilen den Inhalt der Nachricht bilden.
  • Zeile 16: Der Server antwortet, dass die Nachricht gesendet werden kann. Diese besteht aus einer Folge von Textzeilen, die mit einer Zeile enden muss, die aus einem einzigen Zeichen besteht, nämlich einem Punkt.
  • Zeilen 17–25: Die vom Client gesendete Nachricht
  • Zeilen 17–19: Die Kopfzeilen der Nachricht [From:, To:, Subject:] geben jeweils den Absender, den Empfänger und den Betreff der Nachricht an.
  • Zeile 20: Leere Zeile, die das Ende der Kopfzeilen signalisiert
  • Zeilen 21–23: Der Nachrichtentext
  • Zeile 24: Die aus einem einzigen Punkt bestehende Zeile, die das Ende der Nachricht signalisiert.
  • Zeile 26: Der SMTP-Server antwortet, dass er die Nachricht akzeptiert
  • Zeile 27: Der Client sendet den Befehl [QUIT], um anzuzeigen, dass er fertig ist
  • Zeile 28: Der SMTP-Server antwortet ihm, dass er die Verbindung zum Client schließen wird

Kommentare zum Code

Wir werden nicht näher auf den Code des Skripts eingehen, da er ausführlich kommentiert wurde.

  • Zeilen 48–80: Die Funktion, die die Datei „[infos.txt]“ verarbeitet, die die zu versendende Nachricht sowie die für den Versand erforderlichen Informationen enthält. Sie gibt ein Array ($erreur, $smtpServer, $expéditeur, $destinataire, $messge) zurück, das Folgendes enthält:
    • $erreur: eine eventuelle Fehlermeldung, andernfalls leer.
    • $smtpServer: den Namen des SMTP-Servers, mit dem eine Verbindung hergestellt werden soll
    • $expéditeur: die E-Mail-Adresse des Absenders
    • $destinataire: die E-Mail-Adresse des Empfängers
    • $message: Die zu versendende Nachricht. Neben dem Nachrichtentext kann sie auch Kopfzeilen enthalten.
  • Zeilen 84–157: Die Funktion sendMail ist für den Versand der Nachricht zuständig. Ihre Parameter lauten wie folgt:
    • $smtpServer: Der Name des SMTP-Servers, mit dem eine Verbindung hergestellt werden muss
    • $expéditeur: die E-Mail-Adresse des Absenders
    • $destinataire: die E-Mail-Adresse des Empfängers
    • $message: Die zu versendende Nachricht.
    • $verbose: Der Wert 1 gibt an, dass der Datenaustausch mit dem SMTP-Server auf der Konsole angezeigt werden soll.

Die Funktion sendMail gibt eine Fehlermeldung zurück, die leer ist, wenn kein Fehler aufgetreten ist.

  • Zeile 88: Ermöglicht es, den Windows-Namen eines Computers abzurufen, auf dem Windows läuft (OS).
  • Zeile 99: Wir haben gesehen, dass der Client-Server-Dialog wie folgt abläuft:
    • Senden eines Befehls in einer Zeile durch den Client
    • Antwort des Servers in einer oder mehreren Zeilen
  • Zeilen 161–208: Die Funktion sendCommand akzeptiert die folgenden Parameter:
    • $connexion: den Kanal TCP / IP, der den Client mit dem Server verbindet
    • $commande: Der über diesen Kanal zu sendende Befehl. Die Antwort des Servers auf diesen Befehl wird ausgelesen.
    • $verbose: Der Wert 1 gibt an, dass der Datenaustausch mit dem SMTP-Server auf der Konsole angezeigt werden soll.
    • $withRCLF: Der Wert 1 gibt an, dass am Ende des Befehls das Zeilenendezeichen „\r\n“ hinzugefügt werden soll
  • Zeile 173: Versand des Befehls durch den Client
  • Zeile 181: Einlesen der ersten Zeile der Antwort des SMTP-Servers in der Form „xxx Text“ oder „xxx-Text“. Im letzteren Fall gibt der Server an, dass noch eine weitere Zeile gesendet werden muss. „xxx“ ist der vom Server gesendete Fehlercode.
  • Zeile 188 – Abruf des Fehlercodes aus der Antwort
  • Zeilen 191–199: Lesen der übrigen Zeilen der Antwort
  • Zeilen 203–204: Ist der Fehlercode >=500, so meldet der SMTP-Server einen Fehler.

9.4. Ein zweites Programm zum Versenden von E-Mails (inet_04)

Dieses Skript hat dieselbe Funktion wie das vorherige: das Versenden einer E-Mail. Dazu verwenden wir Module aus der Bibliothek PEAR. Diese Bibliothek umfasst Dutzende von Modulen, die verschiedene Bereiche abdecken. Wir werden die folgenden verwenden:

  • Net/SMTP: ein Modul zur Kommunikation mit einem Server SMTP
  • Mail: ein Modul, mit dem der Versand einer E-Mail über verschiedene Protokolle verwaltet werden kann.
  • Mail/Mime: ein Modul zum Erstellen einer Nachricht, die angehängte Dokumente enthalten kann.

Um diese Module nutzen zu können, müssen sie zunächst auf dem Rechner installiert werden, auf dem das Skript PHP ausgeführt wird. Durch die Installation des Softwarepakets WampServer wurde ein Interpreter PHP installiert. In dessen Verzeichnisbaum können Module PEAR installiert werden.

  • in [1], den Installationsordner des Interpreters PHP
  • in [2], den Ordner PEAR, der die Module PEAR enthält, die installiert werden sollen
  • in [3], die Befehlsdatei [go-pear.bat], die die Bibliothek PEAR initialisiert

Um die Bibliothek PEAR zu initialisieren, öffnet man ein Fenster DOS und führt die Datei [go-pear.bat] aus. Dieses Skript stellt eine Verbindung zur Website der Bibliothek PEAR her. Dazu ist eine Internetverbindung erforderlich.

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>go-pear.bat

Nach der Verbindung mit der Website der Bibliothek PEAR lädt das Skript eine Reihe von Elementen herunter. Darunter befindet sich ein neues Skript [pear.bat]. Mit diesem Skript installieren wir die verschiedenen Module PEAR, die wir benötigen. Dieses Skript wird mit Argumenten aufgerufen. Unter diesen ermöglicht das Argument [help] die Anzeige einer Liste der vom Skript akzeptierten Befehle:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear help
Commands:
build                  Build an Extension From C Source
bundle                 Unpacks a Pecl Package
channel-add            Add a Channel
channel-alias          Specify an alias to a channel name
channel-delete         Remove a Channel From the List
channel-discover       Initialize a Channel from its server
channel-info           Retrieve Information on a Channel
channel-login          Connects and authenticates to remote channel server
channel-logout         Logs out from the remote channel server
channel-update         Update an Existing Channel
clear-cache            Clear Web Services Cache
config-create          Create a Default configuration file
config-get             Show One Setting
config-help            Show Information About Setting
config-set             Change Setting
config-show            Show All Settings
convert                Convert a package.xml 1.0 to package.xml 2.0 format
cvsdiff                Run a "cvs diff" for all files in a package
cvstag                 Set CVS Release Tag
download               Download Package
download-all           Downloads each available package from the default channel

info                   Display information about a package
install                Install Package
list                   List Installed Packages In The Default Channel
list-all               List All Packages
list-channels          List Available Channels
list-files             List Files In Installed Package
list-upgrades          List Available Upgrades
login                  Connects and authenticates to remote server [Deprecated i
n favor of channel-login]
logout                 Logs out from the remote server [Deprecated in favor of c
hannel-logout]
makerpm                Builds an RPM spec file from a PEAR package
package                Build Package
package-dependencies   Show package dependencies
package-validate       Validate Package Consistency
pickle                 Build PECL Package
remote-info            Information About Remote Packages
remote-list            List Remote Packages
run-scripts            Run Post-Install Scripts bundled with a package
run-tests              Run Regression Tests
search                 Search remote package database
shell-test             Shell Script Test
sign                   Sign a package distribution file
svntag                 Set SVN Release Tag
uninstall              Un-install Package
update-channels        Update the Channel List
upgrade                Upgrade Package
upgrade-all            Upgrade All Packages [Deprecated in favor of calling upgr
ade with no parameters]
Usage: pear [options] command [command-options] <parameters>
Type "pear help options" to list all options.
Type "pear help shortcuts" to list all command shortcuts.
Type "pear help <command>" to get the help for the specified command.

Mit dem Befehl [install] können Module vom Typ PEAR installiert werden. Hilfe zum Befehl [install] kann wie folgt angefordert werden:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear help install
pear install [options] [channel/]<package> ...
Installs one or more PEAR packages.  You can specify a package to install in four ways:

"Package-1.0.tgz" : installs from a local file

"http://example.com/Package-1.0.tgz" : installs from anywhere on the net.

"package.xml" : installs the package described in package.xml.  Useful for testing, or for wrapping a PEAR package in another package manager such as RPM.

"Package[-version/state][.tar]" : queries your default channel's server(pear.php.net) and downloads the newest package with the preferred quality/state (stable).

To retrieve Package version 1.1, use "Package-1.1," to retrieve Package state beta, use "Package-beta."  To retrieve an uncompressed file, append .tar (make sure there is no file by the same name first)

To download a package from another channel, prefix with the channel name like "channel/Package"

More than one package may be specified at once.  It is ok to mix these four ways of specifying packages.

Options:
  -f, --force
        will overwrite newer installed packages
  -l, --loose
        do not check for recommended dependency version
  -n, --nodeps
        ignore dependencies, install anyway
  -r, --register-only
        do not install files, only register the package as installed
  -s, --soft
        soft install, fail silently, or upgrade if already installed
  -B, --nobuild
        don't build C extensions
  -Z, --nocompress
        request uncompressed files when downloading
  -R DIR, --installroot=DIR
        root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM
  -P DIR, --packagingroot=DIR
        root directory used when packaging files, like RPM packaging
  --ignore-errors
        force install even if there were errors
  -a, --alldeps
        install all required and optional dependencies
  -o, --onlyreqdeps
        install all required dependencies
  -O, --offline
        do not attempt to download any urls or contact channels
  -p, --pretend
        Only list the packages that would be downloaded

Die folgenden Module PEAR müssen installiert werden: [Mail], [Mail_Mime], [Net_SMTP]. Im DOS-Fenster geben Sie nacheinander die folgenden Befehle ein:

<PHP_installDir>pear install Mail
...
<PHP_installDir>pear install Mail_Mime
<PHP_installDir>pear install Net_SMTP

wobei <PHP_installDir> der Installationsordner des Interpreters PHP ist (in diesem Beispiel C:\serveursSGBD\wamp21\bin\PHP\php5.3.5)

Die installierten Module sind wie folgt ersichtlich:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear list
INSTALLED PACKAGES, CHANNEL PEAR.php.NET:
=========================================
PACKAGE          VERSION STATE
Archive_Tar      1.3.7   stable
Console_Getopt   1.3.1   stable
Mail             1.2.0   stable
Mail_Mime        1.8.1   stable
Net_SMTP         1.6.0   stable
Net_Socket       1.0.10  stable
PEAR             1.9.4   stable
PHPUnit          1.3.2   stable
Structures_Graph 1.0.4   stable
XML_Util         1.2.1   stable

Die Module sind im Ordner <PHP_installDir>/PEAR installiert:

Wenn die Module PEAR installiert sind, sieht das Skript PHP zum Versenden von E-Mails wie folgt aus:


<?php

// Fehlerbehandlung
ini_set("display_errors", "off");
// Module
ini_set("include_path", ".;C:\serveursSGBD\wamp21\bin\PHP\php5.3.5\PEAR");
require_once "Mail.php";
require_once "Mail/Mime.php";
require_once "Net/SMTP.php";


// Client SMTP (SendMail-Übertragungsprotokoll) zum Senden einer Nachricht
// Die Informationen stammen aus einer Datei mit dem Namen $INFOS, die folgende Zeilen enthält
// Zeile 1: SMTP, Absender, Empfänger, Anhang
// folgende Zeilen: der Text der Nachricht
// Absender: E-Mail-Adresse des Absenders
// Empfänger: E-Mail-Adresse des Empfängers
// SMTP: Name des zu verwendenden SMTP-Servers
// Anhang: Name des anzuhängenden Dokuments
// 
// Daten
$INFOS = "mail2.txt"; // die Parameter für den E-Mail-Versand
// Die E-Mail-Einstellungen werden abgerufen
list($erreur, $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) = getInfos($INFOS);
// Fehler?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire,$sujet, $attachement]\n";
// Versenden der E-Mail im ausführlichen Modus
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
print "Résultat de l'envoi : $résultat\n";
// Ende
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
// gibt die Informationen zurück ($smtp,$expéditeur,$destinataire,$message, $sujet, $attachement) aus der Textdatei $fichier
// Zeile 1: SMTP, Absender, Empfänger, Betreff, Anhang
// folgende Zeilen: der Text der Nachricht
...
// Zeilenumbruch
  return array("", $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
}

//getInfos
//-----------------------------------------------------------------------

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) {
// sendet $message an den SMTP-Server $smtpserver im Namen von $expéditeur
// an $destinataire. Das Dokument $attachement ist der Nachricht angehängt
// Die Nachricht hat den Betreff $sujet
// 
  // Nachricht
  $msg = new Mail_Mime();
  $msg->setTXTBody($message);
  $msg->addAttachment($attachement);
  $headers = $msg->headers(array("From" => $expéditeur, "To" => $destinataire, "Subject" => $sujet));
  // Versand
  $mailer = &Mail::factory("smtp", array("host" => $smtpServer, "port" => 25));
  $envoi = $mailer->send($expéditeur, $headers, $msg->get());
  if ($envoi === TRUE) {
    return "Message envoyé";
  } else {
    return $envoi;
  }
}

// --------------------------------------------------------------------------

function cutNewLinechar($ligne) {
// Das Zeilenendezeichen von $ligne wird entfernt, falls vorhanden
  
}

Die Datei [mail2.txt]:

1
2
3
4
smtp.orange.fr, serge.tahe@univ-angers.fr , serge.tahe@univ-angers.fr, test, document.pdf
ligne1
ligne2
ligne3
  • Zeile 1: in dieser Reihenfolge der Server SMTP, die Absenderadresse, die Empfängeradresse, der Betreff der Nachricht, das anzuhängende Dokument.
  • Zeilen 2–4: der Text der Nachricht

Bildschirmanzeige

Envoi du message [smtp.orange.fr,serge.tahe@univ-angers.fr,serge.tahe@univ-angers.fr,test, document.pdf]
Résultat de l'envoi : Message envoyé

Kommentare

Das Skript unterscheidet sich vom vorherigen lediglich durch seine Funktion sendmail. Diese beschreiben wir wie folgt:

  • Zeile 6: Die Skripte PHP der Module PEAR wurden in einem Verzeichnis installiert, das standardmäßig nicht vom Interpreter PHP durchsucht wird. Damit dieser die Module PEAR findet, legen wir selbst fest, welche Ordner der Interpreter PHP durchsuchen soll. Es ist möglich, bestimmte Konfigurationsparameter des Interpreters PHP zur Laufzeit zu ändern. Diese Änderung ist nur für das Skript sichtbar, das sie vornimmt, und nur für die Dauer seiner Ausführung. Die Standardkonfiguration des Interpreters PHP befindet sich in der Datei <PHP_installdir>/PHP.ini. Diese Datei enthält Zeilen der Form
clé=valeur

Der Wert des Schlüssels kann zur Laufzeit über die Funktion ini_set(Schlüssel, nouvelle_valeur) geändert werden. Der Schlüssel zur Angabe des Suchpfads, den der Interpreter für die im Skript referenzierten Funktionen und Klassen PHP verwendet, lautet „include_path“. Hier fügen wir dem Suchpfad sowohl den Skriptordner (.) als auch den Ordner „PEAR“ aus dem Installationsordner des Interpreters „PHP“ hinzu.

  • Zeilen 7–9: Die Skripte PHP zum Versenden von E-Mails werden geladen.
  • Zeile 50: Die Funktion sendmail, die für den Versand der E-Mail zuständig ist. Ihre Parameter lauten wie folgt:
    • $smtpServer: Name des SMTP-Servers, mit dem eine Verbindung hergestellt werden soll
    • $expéditeur: die E-Mail-Adresse des Absenders
    • $destinataire: die E-Mail-Adresse des Empfängers
    • $message: die zu versendende Nachricht.
    • $sujet: der Betreff der Nachricht
    • $attachement: Name des an die Nachricht anzuhängenden Dokuments

Die Funktion sendMail gibt eine Fehlermeldung zurück, die leer ist, wenn kein Fehler aufgetreten ist.

  • Zeile 56: Erstellung einer Nachricht vom Typ Mail_Mime. Diese Nachricht besteht aus Kopfzeilen (From, To, Subject) und einem Textkörper (der Nachricht selbst)
  • Zeile 57: Der Textkörper der Nachricht Mail_Mime wird festgelegt.
  • Zeile 58: Ein Dokument wird an die Nachricht angehängt.
  • Zeile 59: Die Kopfzeilen (From, To, Subject) der Nachricht Mail_Mime werden festgelegt
  • Zeile 61: Es wird die Klasse erstellt, die für den Versand der Nachricht Mail_Mime zuständig ist. Der erste Parameter der Methode ist der Name des zu verwendenden Protokolls, hier das Protokoll SMTP. Der zweite Parameter ist ein Array, das den Namen und den Port des zu verwendenden SMTP-Dienstes festlegt
  • Zeile 62: Versand der Nachricht. Die Methode „send“ erhält drei Parameter: die Absenderadresse, die Kopfzeilen der Nachricht Mail_Mime und den Nachrichtentext Mail_Mime. Die Funktion „send“ gibt den booleschen Wert TRUE zurück, wenn der Versand erfolgreich war, andernfalls eine Fehlermeldung.