Skip to content

9. وظائف الشبكة في PHP

سنناقش الآن وظائف الشبكة في PHP، والتي تسمح لنا بتنفيذ برمجة TCP/IP (بروتوكول التحكم في الإرسال/بروتوكول الإنترنت).

9.1. استرداد اسم أو عنوان IP لجهاز على الإنترنت (inet_01)


<?php
 
// functions machine name <--> address IP machine
ini_set("display_errors", "off");
// constants
$HOTES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "localhost", "", "xx");
// IP addresses of $HOTES machines
for ($i = 0; $i < count($HOTES); $i++) {
  getIPandName($HOTES[$i]);
}
// end
exit;
 
//------------------------------------------------
function getIPandName($nomMachine) {
//$nomMachine: name of the machine whose address is required IP: name of the machine whose address is required IP: name of the machine whose address is required
// nomMachine-->adresse IP
  $ip = gethostbyname($nomMachine);
  if ($ip != $nomMachine) {
    print "ip[$nomMachine]=$ip\n";
// address 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";
  }
}

النتائج:

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

تعليقات

  • السطر 4: نطلب من النظام عدم عرض أخطاء وقت التشغيل.

تُستخدم وظائف الشبكة في PHP في الدالة getIpandName في السطر 15.

  • السطر 18: تسترد الدالة gethostbyname($name) عنوان IP "ip3.ip2.ip1.ip0" للجهاز المسمى $name. إذا كان الجهاز $name غير موجود، تعرض الدالة $name كنتيجة.
  • السطر 22: تسترد الدالة gethostbyaddr($ip) اسم المضيف للجهاز الذي يحمل عنوان IP $ip بالتنسيق "ip3.ip2.ip1.ip0". إذا كان الجهاز $ip غير موجود، فإن الدالة تُرجع $ip كنتيجة.

9.2. عميل ويب ( inet_02)

نص برمجي لاسترداد محتوى صفحة فهرس موقع ويب.


<?php
 
// error management
ini_set("display_errors","off");
// otain the text HTML from URL
// list of websites
$SITES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "xx");
// reading the index pages of the sites in the $SITES table
for ($i = 0; $i < count($SITES); $i++) {
// read site index page $SITES[$i]
  $résultat = getIndex($SITES[$i]);
// result display
  print "$résultat\n";
}//for
// end
exit;
 
//-----------------------------------------------------------------------
function getIndex($site) {
// reads the URL $site/ and stores it in the $site.html file
// create file $site.html
  $html = fopen("$site.html", "w");
  if (!$html)
    return "Erreur lors de la création du fichier $site.html";
 
// open a connection on port 80 of $site
  $connexion = fsockopen($site, 80);
// return if error
  if (!$connexion)
    return "Echec de la connexion au site ($site,80) : $erreur";
// $connexion represents a bidirectional communication flow
// between the client (this program) and the contacted web server
// this channel is used for the exchange of orders and information
// the dialog protocol is HTTP
// the customer sends the get command to request URL /
// syntaxe get URL HTTP/1.0
// protocol HTTP headers must end with an empty line
  fputs($connexion, "GET / HTTP/1.0\n\n");
// the server will now respond on channel $connexion. It will send all
// then close the channel. The client therefore reads everything that arrives from $connexion
// until the channel closes
  while ($ligne = fgets($connexion, 1000))
    fputs($html, $ligne);
// the customer in turn closes the connection
  fclose($connexion);
// close file $html
  fclose($html);
// return
  return "Transfert réussi de la page index du site $site";
}

النتائج: على سبيل المثال، الملف الذي تم استلامه للموقع [www.ibm.com]:

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>
  • الأسطر 1–11 هي رؤوس HTTP لاستجابة الخادم
  • السطر 1: يوجه الخادم العميل إلى إعادة التوجيه إلى عنوان URL المحدد في السطر 8
  • السطر 2: تاريخ ووقت الاستجابة
  • السطر 3: هوية خادم الويب
  • السطر 4: المحتوى المرسل من الخادم. هنا، صفحة HTML تبدأ في السطر 13
  • السطر 12: السطر الفارغ الذي ينهي رؤوس HTTP
  • الأسطر 13–19: صفحة HTML التي أرسلها خادم الويب.

تعليقات على الكود:

  • السطر 7: قائمة عناوين URL لمواقع الويب التي نريد صفحاتها الرئيسية. سيتم تخزين هذه العناوين في ملف نصي [sitename.html].
  • السطر 11: تقوم الدالة getIndex بهذه المهمة
  • السطر 19: تقوم الدالة getIndex($site) بتنزيل الصفحة الجذرية (أو الصفحة الرئيسية) لموقع الويب $site وتخزينها في الملف النصي $site.html.
  • السطر 27: تقوم الدالة fsockopen($site,$port) بإنشاء اتصال بخدمة TCP/IP تعمل على المنفذ $port لجهاز $site. بمجرد فتح اتصال العميل/الخادم، تتبادل العديد من خدمات TCP/IP أسطر النص. وهذا هو الحال هنا مع HTTP (بروتوكول نقل النص التشعبي). يمكن بعد ذلك التعامل مع تدفق البيانات من الخادم إلى العميل كملف نصي. وينطبق الأمر نفسه على تدفق البيانات من العميل إلى الخادم.
  • السطر 38: تسمح الدالة fputs للعميل بإرسال البيانات إلى الخادم. هنا، السطر النصي المرسل له المعنى التالي: "أريد (GET) الصفحة الجذرية (/) للموقع الإلكتروني الذي أنا متصل به. أنا أستخدم HTTP الإصدار 1.0." الإصدار الحالي لهذا البروتوكول هو 1.1.
  • السطر 42: يمكن قراءة الأسطر النصية لاستجابة الخادم سطراً سطراً باستخدام حلقة while وحفظها في الملف النصي [$site.html]. بمجرد أن يرسل خادم الويب الصفحة المطلوبة، فإنه يغلق اتصاله مع العميل. على جانب العميل، سيتم اكتشاف ذلك على أنه نهاية الملف.

9.3. عميل SMTP (inet_03)

من بين بروتوكولات TCP/IP، يعد SMTP (بروتوكول نقل البريد البسيط) بروتوكول الاتصال لخدمة توصيل البريد.

ملاحظات:

  • على جهاز يعمل بنظام Windows مزود ببرنامج مكافحة فيروسات، من المحتمل أن يمنع برنامج مكافحة الفيروسات البرنامج النصي PHP من الاتصال بالمنفذ 25 لخادم SMTP. لذلك، يجب تعطيل برنامج مكافحة الفيروسات. بالنسبة لبرنامج McAfee، على سبيل المثال، يمكنك القيام بذلك:
  • في [1]، افتح وحدة تحكم VirusScan
  • في [2]، أوقف خدمة [On-Access Protection]
  • في [3]، تم إيقافها

النص البرمجي:


<?php
 
// client SMTP (SendMail Transfer Protocol) for sending a message
// information is taken from a $INFOS file containing the following lines
// line 1: smtp, sender, recipient
// next lines: message text
// sender: email sender
// recipient: email recipient
// smtp: name of smtp server to use
// communication protocol SMTP client-server
// -> client connects to smtp server port 25
// <- server sends him a welcome message
// -> customer sends command EHLO: machine name
// <- server responds OK or not
// -> customer sends mail order from: <sender>
// <- server responds OK or not
// -> client sends the rcpt to command: <recipient>
// <- server responds OK or not
// -> customer sends data order
// <- server responds OK or not
// -> client sends all the lines of its message and ends with a line containing the
// single character .
// <- server responds OK or not
// -> customer sends quit order
// <- server responds OK or not
// server responses have the form xxx text where xxx is a 3-digit number. Any number xxx >=500
// indicates an error. The answer may consist of several lines all beginning with xxx except the last one
// of the form xxx(space)
// exchanged text lines must end with the characters RC(#13) and LF(#10)
 
// data
$INFOS = "mail.txt"; // mail settings
// retrieve mail parameters
list($erreur, $smtpServer, $expéditeur, $destinataire, $message) = getInfos($INFOS);
// mistake?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire]\n";
// sending mail in verbose mode
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, 1);
print "Résultat de l'envoi : $résultat\n";
// end
exit;
 
//-----------------------------------------------------------------------
function getInfos($fichier) {
// returns information ($smtp,$expéditeur,$destinataire,$message) taken from text file $fichier
// line 1: smtp, sender, recipient
// next lines: message text
 
// opening of $fichier
  $infos = fopen($fichier, "r");
// does the $fichier file exist?
  if (!$infos)
    return array("Le fichier $fichier n'a pu être ouvert en lecture");
// read the 1st line
  $ligne = fgets($infos, 1000);
// delete end-of-line mark
  $ligne = cutNewLineChar($ligne);
// retrieving smtp, sender and recipient fields
  $champs = explode(",", $ligne);
// do we have the right number of fields?
  if (count($champs) != 3)
    return "La ligne 1 du fichier $fichier (serveur smtp, expéditeur, destinataire) a un
nombre de champs incorrect";
// "processing" the recovered information
  for ($i = 0; $i < count($champs); $i++)
    $champs[$i] = trim($champs[$i]);
// field recovery
  list($smtpServer, $expéditeur, $destinataire) = $champs;
// read message
  $message = "";
  while ($ligne = fgets($infos, 1000))
    $message.=$ligne;
  fclose($infos);
// return
  return array("", $smtpServer, $expéditeur, $destinataire, $message);
}
 
//-----------------------------------------------------------------------
 
function sendmail($smtpServer, $expéditeur, $destinataire, $message, $verbose) {
// sends $message to smtp server $smtpserver from $expéditeur
// for $destinataire. If $verbose=1, tracks client-server exchanges
// retrieve the customer's name
  $client = gethostbyaddr(gethostbyname(""));
// open a connection on port 25 of $smtpServer
  $connexion = fsockopen($smtpServer, 25);
// return if error
  if (!$connexion)
    return "Echec de la connexion au site ($smtpServer,25)";
// $connexion represents a bidirectional communication flow
// between the client (this program) and the smtp server contacted
// this channel is used for the exchange of orders and information
 
// after connection, the server sends a welcome message which is read as follows
  $erreur = sendCommand($connexion, "", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// cmde ehlo:
  $erreur = sendCommand($connexion, "EHLO $client", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// cmde mail from:
  $erreur = sendCommand($connexion, "MAIL FROM: <$expéditeur>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// cmde rcpt to:
  $erreur = sendCommand($connexion, "RCPT TO: <$destinataire>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// cmde data
  $erreur = sendCommand($connexion, "DATA", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// prepare message to send
  // it must contain the lines
  // From: expéditeur
  // To: recipient
  // blank line
  // Message
  // .
  $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;
  }
 
// cmde quit
  $erreur = sendCommand($connexion, "QUIT", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }
 
// end
  fclose($connexion);
  return "Message envoyé";
}
 
// --------------------------------------------------------------------------
 
function sendCommand($connexion, $commande, $verbose, $withRCLF) {
// sends $commande to the $connexion channel
// verbose mode if $verbose=1
// if $withRCLF=1, adds sequence RCLF to exchange
 
// data
  if ($withRCLF)
    $RCLF = "\r\n"; else
    $RCLF="";
 
// send cmde if $commande not empty
  if ($commande) {
    fputs($connexion, "$commande$RCLF");
 
// possible echo
    if ($verbose)
      affiche($commande, 1);
  }////if
 
// reading response
  $réponse = fgets($connexion, 1000);
 
// possible echo
  if ($verbose)
    affiche($réponse, 2);
 
// error code recovery
  $codeErreur = substr($réponse, 0, 3);

// last line of the answer?
  while (substr($réponse, 3, 1) == "-") {
 
     // reading response
    $réponse = fgets($connexion, 1000);
 
     // possible echo
    if ($verbose)
      affiche($réponse, 2);
  }////while
// answer completed
 
// error returned by the server?
  if ($codeErreur >= 500)
    return substr($réponse, 4);
 
// error-free return
  return "";
}
 
// --------------------------------------------------------------------------
 
function affiche($échange, $sens) {
// displays $échange on screen
// if $sens=1 displays -->$echange
// if $sens=2 displays <-- $échange without the last 2 characters RCLF
  switch ($sens) {
    case 1:
      print "--> [$échange]\n";
      return;
    case 2:
      $L = strlen($échange);
      print "<-- [" . substr($échange, 0, $L - 2) . "]\n";
      return;
  }////switch
}
 
// --------------------------------------------------------------------------
 
function cutNewLinechar($ligne) {
// delete the end-of-line mark from $ligne if it exists
  ...
}

ملف 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
  • السطر 1: [smtp.orange.fr] الخادم المستخدم لإرسال البريد الإلكتروني، [serge.tahe@univ-angers.fr] عنوان المرسل، [serge.tahe@istia.univ-angers.fr] عنوان المستلم
  • السطر 2: رؤوس الرسالة. يوجد هنا رأس واحد فقط، وهو موضوع الرسالة.
  • السطر 3: السطر الفارغ ينهي رؤوس الرسالة
  • الأسطر 4–7: نص الرسالة

نتائج الشاشة:

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é
  • السطر 1: رسالة تتبع تنفيذ البرنامج النصي
  • السطر 2: أول استجابة من خادم SMTP. يأتي هذا بعد اتصال العميل بالمنفذ 25 لخادم SMTP. استجابات الخادم هي أسطر على شكل [xxx message] أو [xxx-message]. تشير الصيغة الأولى إلى أن الاستجابة كاملة. xxx هو رمز الحالة. تشير القيمة الأكبر من أو تساوي 500 إلى وجود خطأ. تشير الصيغة الثانية إلى أن الاستجابة غير كاملة وأن سطرًا آخر سيتبعها.
  • السطر 2: يشير خادم SMTP إلى أنه جاهز لتلقي الأوامر
  • السطر 3: يرسل العميل الأمر [EHLO machineName]، حيث machineName هو اسم المضيف للجهاز الذي يعمل عليه العميل
  • الأسطر 4-10: استجابة من خادم SMTP
  • السطر 11: يرسل العميل الأمر [MAIL FROM: <sender>]، الذي يحدد عنوان البريد الإلكتروني للمرسل.
  • السطر 12: يشير خادم SMTP إلى أنه يقبل هذا العنوان. كان من الممكن أن يرفضه إذا كانت الصيغة غير صحيحة. ومع ذلك، فإنه لا يتحقق من وجود عنوان البريد الإلكتروني فعليًا.
  • السطر 13: يرسل العميل الأمر [RCPT TO: <recipient>]، الذي يحدد عنوان البريد الإلكتروني لمستلم الرسالة.
  • السطر 14: يرد خادم SMTP بأنه يقبل هذا العنوان. ومرة أخرى، يتم إجراء فحص لصيغة العنوان.
  • السطر 15: يرسل العميل الأمر [DATA]، الذي يشير للمستخدم إلى أن الأسطر التالية هي نص الرسالة.
  • السطر 16: يرد الخادم بأنه يمكن إرسال الرسالة. الرسالة عبارة عن سلسلة من الأسطر النصية التي يجب أن تنتهي بسطر مكون من حرف واحد: نقطة.
  • الأسطر 17-25: الرسالة المرسلة من قبل العميل
  • الأسطر 17-19: تشير رؤوس الرسالة [From:, To:, Subject:] إلى المرسل والمستلم وموضوع الرسالة، على التوالي.
  • السطر 20: سطر فارغ يشير إلى نهاية الرؤوس
  • الأسطر 21-23: نص الرسالة
  • السطر 24: السطر المكون من نقطة واحدة التي تشير إلى نهاية الرسالة.
  • السطر 26: يرد خادم SMTP بأنه يقبل الرسالة
  • السطر 27: يرسل العميل الأمر [QUIT] للإشارة إلى أنه قد انتهى
  • السطر 28: يرد خادم SMTP بأنه سيغلق الاتصال بالعميل

تعليقات على الكود

لن نخوض في تفاصيل كثيرة حول كود البرنامج النصي لأنه تم توضيحه بالتفصيل.

  • الأسطر 48–80: الدالة التي تعالج ملف [infos.txt]، الذي يحتوي على الرسالة المراد إرسالها بالإضافة إلى المعلومات الضرورية لإرسالها. وتُرجع مصفوفة ($error, $smtpServer, $sender, $recipient, $message) تحتوي على:
    • $error: رسالة خطأ محتملة؛ وإلا تكون فارغة.
    • $smtpServer: اسم خادم SMTP المراد الاتصال به
    • $sender: عنوان البريد الإلكتروني للمرسل
    • $recipient: عنوان البريد الإلكتروني للمستلم
    • $message: الرسالة المراد إرسالها. بالإضافة إلى نص الرسالة، قد تكون هناك رؤوس.
  • الأسطر 84-157: وظيفة sendMail مسؤولة عن إرسال الرسالة. معلماتها هي كما يلي:
    • $smtpServer: اسم خادم SMTP المراد الاتصال به
    • $sender: عنوان البريد الإلكتروني للمرسل
    • $recipient: عنوان البريد الإلكتروني للمستلم
    • $message: الرسالة المراد إرسالها.
    • $verbose: إذا تم تعيينها على 1، فهذا يشير إلى أنه يجب تسجيل الاتصال بخادم SMTP في وحدة التحكم.

تُرجع الدالة sendMail رسالة خطأ؛ وتُرجع سلسلة فارغة في حالة عدم وجود أخطاء.

  • السطر 88: يسترد اسم Windows لجهاز كمبيوتر يعمل بنظام التشغيل Windows.
  • السطر 99: لقد رأينا أن الحوار بين العميل والخادم يتبع هذا النمط:
    • يرسل العميل أمرًا في سطر واحد
    • استجابة الخادم في سطر واحد أو أكثر
  • الأسطر 161–208: تقبل الدالة `sendCommand` المعلمات التالية:
    • $connection: قناة TCP/IP التي تربط العميل بالخادم
    • $command: الأمر المراد إرساله عبر هذه القناة. سيتم قراءة استجابة الخادم لهذا الأمر.
    • $verbose: إذا تم تعيينها على 1، فهذا يشير إلى أنه يجب عرض التبادلات مع خادم SMTP على وحدة التحكم.
    • $withRCLF: إذا تم تعيينه على 1، فهذا يشير إلى أنه يجب إضافة علامة نهاية السطر "\r\n" إلى نهاية الأمر
  • السطر 173: يرسل العميل الأمر
  • السطر 181: قراءة السطر الأول من استجابة خادم SMTP في شكل xxx text أو xxx-text. تشير الحالة الأخيرة إلى أن الخادم لديه سطر آخر لإرساله. xxx هو رمز الخطأ المرسل من الخادم.
  • السطر 188 – استرداد رمز الخطأ من الرد
  • الأسطر 191–199: قراءة الأسطر الأخرى من الرد
  • السطران 203–204: إذا كان رمز الخطأ >=500، فإن خادم SMTP يبلغ عن وجود خطأ.

9.4. برنامج ثانٍ لإرسال البريد الإلكتروني (inet_04)

يتمتع هذا البرنامج النصي بنفس وظيفة البرنامج السابق: إرسال بريد إلكتروني. نستخدم وحدات من مكتبة PEAR لهذا الغرض. تحتوي هذه المكتبة على عشرات الوحدات التي تغطي مجالات متنوعة. سنستخدم ما يلي:

  • Net/SMTP: وحدة للتواصل مع خادم SMTP
  • Mail: وحدة لإدارة إرسال البريد الإلكتروني باستخدام بروتوكولات مختلفة.
  • Mail/Mime: وحدة لإنشاء رسالة يمكن أن تتضمن مستندات مرفقة.

لاستخدام هذه الوحدات، يجب أولاً تثبيتها على الجهاز الذي يعمل عليه البرنامج النصي PHP. أدى تثبيت حزمة برامج WampServer إلى تثبيت مترجم PHP. ويمكنك تثبيت وحدات PEAR ضمن بنية الدلائل الخاصة به.

  • في [1]، دليل تثبيت مترجم PHP
  • في [2]، مجلد PEAR الذي سيحتوي على وحدات PEAR المراد تثبيتها
  • [3] هو ملف الدفعة [go-pear.bat] الذي يقوم بتهيئة مكتبة PEAR

لتهيئة مكتبة PEAR، افتح نافذة DOS وقم بتشغيل الملف [go-pear.bat]. سيتصل هذا البرنامج النصي بموقع مكتبة PEAR. لذلك، يلزم وجود اتصال بالإنترنت.

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

بمجرد الاتصال بموقع مكتبة PEAR، سيقوم البرنامج النصي بتنزيل عدد من العناصر. ومن بينها برنامج نصي جديد [pear.bat]. سنستخدم هذا البرنامج النصي لتثبيت مختلف وحدات PEAR التي نحتاجها. يتم استدعاء هذا البرنامج النصي مع معلمات. ومن بينها، توفر المعلمة [help] قائمة بالأوامر التي يقبلها البرنامج النصي:

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.

يُستخدم الأمر [install] لتثبيت وحدات PEAR. يمكنك الحصول على المساعدة بشأن الأمر [install]:

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

وحدات PEAR المطلوب تثبيتها هي: [Mail]، [Mail_Mime]، [Net_SMTP]. في نافذة موجه الأوامر، أدخل الأوامر التالية واحدة تلو الأخرى:

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

حيث <PHP_installDir> هو دليل تثبيت مترجم PHP (C:\serveursSGBD\wamp21\bin\PHP\php5.3.5 في هذا المثال)

يمكنك عرض الوحدات المثبتة:

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

يتم تثبيت الوحدات النمطية في المجلد <PHP_installDir>/PEAR:

بعد تثبيت وحدات PEAR، يبدو نص PHP الخاص بإرسال البريد الإلكتروني كما يلي:


<?php
 
// error management
ini_set("display_errors", "off");
// modules
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 Transfer Protocol) for sending a message
// information is taken from a $INFOS file containing the following lines
// line 1: smtp, sender, recipient, attachment
// next lines: message text
// sender:email sender
// recipient: email recipient
// smtp: name of smtp server to use
// attachment: name of the document to be attached
// 
// data
$INFOS = "mail2.txt"; // mail settings
// retrieve mail parameters
list($erreur, $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) = getInfos($INFOS);
// mistake?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire,$sujet, $attachement]\n";
// sending mail in verbose mode
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
print "Résultat de l'envoi : $résultat\n";
// end
exit;
 
//-----------------------------------------------------------------------
function getInfos($fichier) {
// returns information ($smtp,$expéditeur,$destinataire,$message, $sujet, $attachement) taken from text file $fichier
// line 1: smtp, sender, recipient, subject, attachment
// next lines: message text
...
// return
  return array("", $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
}
 
//getInfos
//-----------------------------------------------------------------------
 
function sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) {
// sends $message to smtp server $smtpserver from $expéditeur
// for $destinataire. Document $attachement is attached to the message
// message has subject $sujet
// 
  // message
  $msg = new Mail_Mime();
  $msg->setTXTBody($message);
  $msg->addAttachment($attachement);
  $headers = $msg->headers(array("From" => $expéditeur, "To" => $destinataire, "Subject" => $sujet));
  // shipping
  $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) {
// delete the end-of-line mark from $ligne if it exists
  
}

ملف [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
  • السطر 1: بالترتيب، خادم SMTP، عنوان المرسل، عنوان المستلم، موضوع الرسالة، المستند المراد إرفاقه.
  • السطور 2-4: نص الرسالة

نتائج الشاشة

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é

تعليقات

يختلف هذا البرنامج النصي عن البرنامج النصي السابق فقط في استخدامه لوظيفة sendmail. نصف هذه الوظيفة أدناه:

  • السطر 6: تم تثبيت نصوص PHP الخاصة بوحدات PEAR في دليل لا يبحث فيه مترجم PHP بشكل افتراضي. لضمان أن المترجم يمكنه العثور على وحدات PEAR، نحدد يدويًا الدلائل التي يجب أن يبحث فيها. من الممكن تعديل بعض معلمات التكوين لمترجم PHP أثناء التشغيل. هذا التعديل مرئي فقط للنص البرمجي الذي يقوم به وفقط طوال مدة تنفيذه. يمكن العثور على التكوين الافتراضي لمترجم PHP في الملف <PHP_installdir>/PHP.ini. يحتوي هذا الملف على أسطر بالشكل
clé=valeur

يمكن تعديل قيمة المفتاح أثناء التشغيل باستخدام الدالة ini_set(key, new_value). المفتاح المستخدم لتحديد مسار البحث عن دوال وفئات PHP التي يشير إليها البرنامج النصي هو 'include_path'. هنا، نضيف كل من دليل البرنامج النصي (.) ودليل PEAR داخل دليل تثبيت مترجم PHP إلى مسار البحث.

  • الأسطر 7–9: يتم تحميل البرامج النصية PHP لإرسال البريد الإلكتروني.
  • السطر 50: دالة sendmail، التي تتولى إرسال البريد الإلكتروني. معلماتها هي كما يلي:
    • $smtpServer: اسم خادم SMTP المراد الاتصال به
    • $sender: عنوان البريد الإلكتروني للمرسل
    • $recipient: عنوان البريد الإلكتروني للمستلم
    • $message: الرسالة المراد إرسالها.
    • $subject: موضوع الرسالة
    • $attachment: اسم المستند المراد إرفاقه بالرسالة

تُرجع الدالة sendMail رسالة خطأ؛ وتكون فارغة في حالة عدم حدوث أي خطأ.

  • السطر 56: إنشاء رسالة Mail_Mime. تتكون هذه الرسالة من رؤوس (From، To، Subject) ونص (الرسالة نفسها)
  • السطر 57: يتم تعيين نص رسالة Mail_Mime.
  • السطر 58: إرفاق مستند بالرسالة
  • السطر 59: تعيين الرؤوس (From، To، Subject) لرسالة Mail_Mime
  • السطر 61: إنشاء الفئة المسؤولة عن إرسال رسالة Mail_Mime. المعلمة الأولى للطريقة هي اسم البروتوكول المراد استخدامه، وهو في هذه الحالة بروتوكول SMTP. المعلمة الثانية هي مصفوفة تحدد اسم ومنفذ خدمة SMTP المراد استخدامها
  • السطر 62: إرسال الرسالة. تأخذ طريقة الإرسال ثلاث معلمات: عنوان المرسل، ورؤوس رسالة Mail_Mime، ونص رسالة Mail_Mime. ترجع دالة الإرسال القيمة المنطقية TRUE إذا تم إرسال الرسالة بنجاح، أو رسالة خطأ في حالة عدم نجاح الإرسال.