Skip to content

9. فعالیت‌های شبکه‌ای PHP

اکنون به توابع شبکه PHP می‌پردازیم که به ما امکان برنامه‌ریزی TCP / IP (پروتکل انتقال کنترل / پروتکل اینترنت) را می‌دهند.

9.1. به‌دست‌آوردن نام یا آدرس IP یک ماشین در اینترنت (inet_01)


<?php

// توابع: نام ماشین <--> آدرس ماشین IP
ini_set("display_errors", "off");
// ثوابت
$HOTES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "localhost", "", "xx");
// آدرس‌های IP ماشین‌ها در $HOTES
for ($i = 0; $i < count($HOTES); $i++) {
  getIPandName($HOTES[$i]);
}
//پایان
exit;

//------------------------------------------------
function getIPandName($nomMachine) {
//$nomMachine: نام ماشینی است که آدرس آن مورد نیاز است IP
// nomMachine-->آدرس IP
  $ip = gethostbyname($nomMachine);
  if ($ip != $nomMachine) {
    print "ip[$nomMachine]=$ip\n";
// آدرس 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

توضیحات

  • خط ۴: این به سیستم دستور می‌دهد که خطاهای زمان اجرا را نمایش ندهد.

تابع‌های شبکه PHP در تابع getIpandName در خط ۱۵ استفاده می‌شوند.

  • خط ۱۸: تابع gethostbyname($nom) برای به‌دست‌آوردن آدرس IP "ip3.ip2.ip1.ip0" ماشین با نام $nom استفاده می‌شود. اگر ماشین $nom وجود نداشته باشد، تابع $nom را به‌عنوان نتیجه بازمی‌گرداند.
  • خط ۲۲: تابع `gethostbyaddr($ip)` نام میزبان برای ماشین با آدرس `$ip` را در قالب "ip3.ip2.ip1.ip0" بازیابی می‌کند. اگر ماشین $ip وجود نداشته باشد، تابع مقدار $ip را برمی‌گرداند.

9.2. یک کلاینت وب ( inet_02)

یک اسکریپت برای بازیابی محتوای صفحهٔ اصلی یک وب‌سایت.


<?php

// مدیریت خطا
ini_set("display_errors","off");
//بازیابی متن HTML از URL
// فهرست وب‌سایت‌ها
$SITES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "xx");
// خواندن صفحات نمایه وب‌سایت‌ها در جدول $SITES
for ($i = 0; $i < count($SITES); $i++) {
// صفحهٔ فهرست سایت $SITES[$i] را بخوانید
  $résultat = getIndex($SITES[$i]);
//نمایش نتیجه
  print "$résultat\n";
}//برای
//پایان
exit;

//-----------------------------------------------------------------------
function getIndex($site) {
// فایل URL $site/ را می‌خواند و آن را در فایل $site.html ذخیره می‌کند
// فایل $site.html را ایجاد می‌کند
  $html = fopen("$site.html", "w");
  if (!$html)
    return "Erreur lors de la création du fichier $site.html";

//یک اتصال روی پورت ۸۰ از $site باز می‌کند
  $connexion = fsockopen($site, 80);
// در صورت خطا بازگرداندن
  if (!$connexion)
    return "Echec de la connexion au site ($site,80) : $erreur";
// $connexion نشان‌دهنده یک جریان ارتباطی دوطرفه است
//بین کلاینت (این برنامه) و وب‌سروری که در حال تماس با آن است
// این کانال برای تبادل دستورات و اطلاعات استفاده می‌شود
//پروتکل ارتباطی HTTP است
// کلاینت فرمان GET را برای درخواست URL / ارسال می‌کند
// دستور GET: URL HTTP/1.0
// سربرگ‌های پروتکل HTTP باید با یک خط خالی پایان یابند
  fputs($connexion, "GET / HTTP/1.0\n\n");
// سرور اکنون در کانال $connexion پاسخ خواهد داد. آن همه را ارسال خواهد کرد
// این داده‌ها را می‌خواند و سپس کانال را می‌بندد. بنابراین کلاینت همه چیز را که از $connexion می‌رسد می‌خواند
//تا زمانی که کانال بسته شود
  while ($ligne = fgets($connexion, 1000))
    fputs($html, $ligne);
// سپس کلاینت اتصال را می‌بندد
  fclose($connexion);
//بستن فایل $html
  fclose($html);
//بازگشت
  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>
  • خطوط ۱–۱۱ سربرگ‌های HTTP از پاسخ سرور هستند
  • خط ۱: سرور به کلاینت دستور می‌دهد تا به URL مشخص‌شده در خط ۸ هدایت کند
  • خط ۲: تاریخ و زمان پاسخ
  • خط ۳: هویت وب‌سرور
  • خط ۴: محتوایی که توسط سرور ارسال می‌شود. در این مورد، یک صفحه HTML که از خط ۱۳ شروع می‌شود
  • خط ۱۲: خط خالی که سربرگ‌ها را پایان می‌دهد
  • خطوط ۱۳–۱۹: صفحه‌ی HTML ارسال‌شده توسط سرور وب.

توضیحات کد:

  • خط ۷: فهرست آدرس‌های وب‌سایت‌هایی که می‌خواهیم صفحهٔ فهرست آن‌ها را دریافت کنیم. این فهرست در فایل متنی [nomsite.html] ذخیره خواهد شد.
  • خط ۱۱: تابع getIndex وظیفه را انجام می‌دهد
  • خط ۱۹: تابع getIndex($site) صفحه ریشه (یا صفحه اصلی) وب‌سایت $site را دانلود کرده و آن را در فایل متنی $site.html ذخیره می‌کند.
  • خط ۲۷: تابع fsockopen($site, $port) برای برقراری ارتباط با سرویس TCP / IP که روی پورت $port در ماشین $site در حال اجرا است. پس از برقراری اتصال کلاینت/سرور، چندین سرویس TCP / IP خطوط متنی را مبادله می‌کنند. این امر در مورد پروتکل HTTP (پروتکل انتقال HyperText) نیز صدق می‌کند. جریان داده از سرور به کلاینت سپس می‌تواند به‌عنوان یک فایل متنی در نظر گرفته شود. همین امر در مورد جریان داده از کلاینت به سرور نیز صدق می‌کند.
  • خط ۳۸: تابع fputs به کلاینت اجازه می‌دهد تا داده‌ها را به سرور ارسال کند. در اینجا، خط متنی ارسالی معنای زیر را دارد: «من صفحه ریشه (/) وب‌سایتی را که به آن متصل هستم (GET) می‌خواهم.» من از پروتکل HTTP، نسخه 1.0 استفاده می‌کنم". نسخه فعلی این پروتکل 1.1 است.
  • خط ۴۲: خطوط متن در پاسخ سرور را می‌توان خط به خط با استفاده از یک حلقه while خواند و در فایل متنی [$site.html] ذخیره کرد. پس از اینکه وب‌سرور صفحه درخواستی را ارسال کرد، اتصال خود را با کلاینت قطع می‌کند. در سمت کلاینت، این وضعیت به‌عنوان پایان فایل تشخیص داده می‌شود.

9.3. یک کلاینت SMTP (inet_03)

در میان پروتکل‌های TCP / IP، SMTP (پروتکل انتقال SendMail) پروتکل ارتباطی برای سرویس ارسال پیام است.

یادداشت‌ها:

  • روی یک سیستم ویندوزی که نرم‌افزار آنتی‌ویروس نصب شده است، برنامه آنتی‌ویروس احتمالاً مانع از اتصال اسکریپت PHP به پورت ۲۵ یک سرور SMTP می‌شود. بنابراین لازم است نرم‌افزار آنتی‌ویروس را غیرفعال کنید. برای مثال، برای McAfee می‌توانید این کار را به شرح زیر انجام دهید:
  • برای [1]، کنسول VirusScan را فعال کنید
  • برای [2]، سرویس [Protection lors de l'accès] را متوقف کنید
  • برای [3]، سرویس متوقف می‌شود

اسکریپت:


<?php

// کلاینت SMTP (پروتکل انتقال SendMail) برای ارسال یک پیام استفاده شد
//اطلاعات از فایلی $INFOS که شامل خطوط زیر است گرفته می‌شود
// خط ۱: SMTP، فرستنده، گیرنده
// خطوط بعدی: متن پیام
// فرستنده: آدرس ایمیل فرستنده
//گیرنده: آدرس ایمیل گیرنده
// SMTP: نام سرور SMTP مورد استفاده
//پروتکل ارتباطی: SMTP کلاینت-سرور
// -> کلاینت به پورت ۲۵ سرور SMTP متصل می‌شود
// <- سرور یک پیام خوش‌آمدگویی برای کلاینت ارسال می‌کند
// -> کلاینت فرمان EHLO را ارسال می‌کند: نام میزبان آن
// <- سرور با OK پاسخ می‌دهد یا خیر
// -> کلاینت فرمان «mail from: <sender>» را ارسال می‌کند
// <- سرور با OK پاسخ می‌دهد یا خیر
//-> کلاینت فرمان rcpt را به: <recipient> ارسال می‌کند
//<- سرور با OK پاسخ می‌دهد یا خیر
// -> کلاینت فرمان 'data' را ارسال می‌کند
// <- سرور با OK پاسخ می‌دهد یا خیر
//-> کلاینت تمام خطوط پیام خود را ارسال می‌کند و با خطی حاوی پایان می‌دهد
// یک کاراکتر واحد.
// <- سرور با OK پاسخ می‌دهد یا خیر
// -> کلاینت فرمان 'quit' را ارسال می‌کند
// <- سرور با OK پاسخ می‌دهد یا خیر
//پاسخ‌های سرور به شکل xxx متن هستند، که در آن xxx یک عدد سه‌رقمی است. هر عددی که xxx ≥ ۵۰۰ باشد
// نشان‌دهنده خطا است. پاسخ ممکن است شامل چندین خط باشد که همه آن‌ها به جز خط آخر با xxx شروع می‌شوند
// به شکل xxx (فاصله)
//خطوط متنی مبادله‌شده باید با کاراکترهای RC(#13) و LF(#10) پایان یابند

// داده‌ها
$INFOS = "mail.txt"; //پارامترها برای ارسال ایمیل
// بازیابی تنظیمات ایمیل
list($erreur, $smtpServer, $expéditeur, $destinataire, $message) = getInfos($INFOS);
// خطا؟
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire]\n";
//ارسال ایمیل در حالت تفصیلی
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, 1);
print "Résultat de l'envoi : $résultat\n";
//پایان
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
//اطلاعات را بازمی‌گرداند ($smtp,$expéditeur,$destinataire,$message) از فایل متنی $fichier
// خط ۱: smtp, فرستنده, گیرنده
// خطوط بعدی: متن پیام

// باز کردن $fichier
  $infos = fopen($fichier, "r");
//آیا فایل $fichier وجود دارد
  if (!$infos)
    return array("Le fichier $fichier n'a pu être ouvert en lecture");
// خواندن خط اول
  $ligne = fgets($infos, 1000);
// حذف کاراکتر پایان خط
  $ligne = cutNewLineChar($ligne);
//بازیابی فیلدهای SMTP، فرستنده و گیرنده
  $champs = explode(",", $ligne);
//آیا تعداد فیلدها صحیح است؟
  if (count($champs) != 3)
    return "La ligne 1 du fichier $fichier (serveur smtp, expéditeur, destinataire) a un
nombre de champs incorrect";
// پردازش اطلاعات بازیابی‌شده
  for ($i = 0; $i < count($champs); $i++)
    $champs[$i] = trim($champs[$i]);
//بازیابی فیلدها
  list($smtpServer, $expéditeur, $destinataire) = $champs;
// خواندن پیام
  $message = "";
  while ($ligne = fgets($infos, 1000))
    $message.=$ligne;
  fclose($infos);
// بازگشت
  return array("", $smtpServer, $expéditeur, $destinataire, $message);
}

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

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $verbose) {
//ارسال می‌کند $message به سرور SMTP $smtpserver به نمایندگی از $expéditeur
//برای $destinataire. اگر $verbose=1 باشد، تبادله‌های کلاینت-سرور را ردیابی می‌کند
//نام مشتری را بازیابی می‌کند
  $client = gethostbyaddr(gethostbyname(""));
//اتصال را روی پورت ۲۵ از $smtpServer باز می‌کند
  $connexion = fsockopen($smtpServer, 25);
//در صورت رخ دادن خطا بازمی‌گردد
  if (!$connexion)
    return "Echec de la connexion au site ($smtpServer,25)";
// $connexion نشان‌دهنده یک جریان ارتباطی دوطرفه است
// بین مشتری (این برنامه) و سرور SMTP مورد تماس
// این کانال برای تبادل دستورات و اطلاعات استفاده می‌شود

// پس از برقراری اتصال، سرور یک پیام خوش‌آمدگویی ارسال می‌کند که خوانده می‌شود
  $erreur = sendCommand($connexion, "", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// دستور 'ehlo':
  $erreur = sendCommand($connexion, "EHLO $client", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// دستور 'mail from':
  $erreur = sendCommand($connexion, "MAIL FROM: <$expéditeur>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// فرمان rcpt به:
  $erreur = sendCommand($connexion, "RCPT TO: <$destinataire>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// دستور داده
  $erreur = sendCommand($connexion, "DATA", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// در حال آماده‌سازی پیام برای ارسال
  // باید شامل خطوط زیر باشد
  // از: فرستنده
  // به: گیرنده
  // خط خالی
  // پیام
  // .
  $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;
  }

// دستور خروج
  $erreur = sendCommand($connexion, "QUIT", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// پایان
  fclose($connexion);
  return "Message envoyé";
}

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

function sendCommand($connexion, $commande, $verbose, $withRCLF) {
//ارسال می‌کند $commande به کانال $connexion
// حالت تفصیلی اگر $verbose=1
//اگر $withRCLF=1 باشد، توالی RCLF را به تبادل اضافه می‌کند

// داده‌ها
  if ($withRCLF)
    $RCLF = "\r\n"; else
    $RCLF="";

// دستور ارسال را ارسال کنید اگر $commande خالی نباشد
  if ($commande) {
    fputs($connexion, "$commande$RCLF");

//اکو احتمالی
    if ($verbose)
      affiche($commande, 1);
  }//اگر

// خواندن پاسخ
  $réponse = fgets($connexion, 1000);

// اکوی احتمالی
  if ($verbose)
    affiche($réponse, 2);

//بازیابی کد خطا
  $codeErreur = substr($réponse, 0, 3);

// آخرین خط پاسخ؟
  while (substr($réponse, 3, 1) == "-") {

     // خواندن پاسخ
    $réponse = fgets($connexion, 1000);

     // بازتاب احتمالی
    if ($verbose)
      affiche($réponse, 2);
  }//در حالی که
// پاسخ کامل

// خطایی که توسط سرور بازگردانده شده؟
  if ($codeErreur >= 500)
    return substr($réponse, 4);

//بدون خطا بازگردانده شد
  return "";
}

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

function affiche($échange, $sens) {
// $échange را روی صفحه نمایش می‌دهد
// اگر $sens=1 باشد، نمایش می‌دهد -->$echange
// اگر $sens=2 باشد، نمایش می‌دهد <-- $échange بدون دو کاراکتر آخر RCLF
  switch ($sens) {
    case 1:
      print "--> [$échange]\n";
      return;
    case 2:
      $L = strlen($échange);
      print "<-- [" . substr($échange, 0, $L - 2) . "]\n";
      return;
  }//سوئیچ
}

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

function cutNewLinechar($ligne) {
// کاراکتر پایان خط از $ligne حذف می‌شود اگر وجود داشته باشد
  ...
}

فایل 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
  • خط ۱: [smtp.orange.fr] – سرور مورد استفاده برای ارسال ایمیل؛ [serge.tahe@univ-angers.fr] – آدرس فرستنده؛ [serge.tahe@istia.univ-angers.fr] – آدرس گیرنده
  • خط ۲: سرآیندهای پیام. در اینجا تنها یکی وجود دارد، موضوع پیام.
  • خط ۳: خط خالی نشان‌دهنده پایان سرآیندهای پیام است
  • خطوط ۴–۷: متن پیام

خروجی صفحه:

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é
  • خط ۱: پیام پیشرفت اجرای اسکریپت
  • خط ۲: اولین پاسخ از سرور SMTP. این پاسخ پس از اتصال کلاینت به پورت ۲۵ سرور SMTP ارسال می‌شود. پاسخ‌های سرور شامل خطوطی به شکل [xxx message] یا [xxx-message] هستند. سینتکس اول نشان می‌دهد که پاسخ کامل است. xxx یک کد وضعیت است. مقدار ۵۰۰ یا بالاتر نشان‌دهنده خطا است. سینتکس دوم نشان می‌دهد که پاسخ کامل نیست و یک خط دیگر دنبال خواهد شد.
  • خط ۲: سرور SMTP نشان می‌دهد که آماده دریافت دستورات است
  • خط ۳: کلاینت فرمان [EHLO nomDeMachine] را ارسال می‌کند، که در آن nomDeMachine نام میزبان ماشینی است که کلاینت روی آن در حال اجرا است
  • خطوط ۴–۱۰: پاسخ از سمت سرور SMTP
  • خط ۱۱: کلاینت فرمان [MAIL FROM: <expéditeur>] را ارسال می‌کند که آدرس ایمیل فرستنده را مشخص می‌کند.
  • خط ۱۲: سرور SMTP نشان می‌دهد که این آدرس را می‌پذیرد. اگر نحو نادرست بود، می‌توانست آن را رد کند. با این حال، بررسی نمی‌کند که آیا آدرس ایمیل واقعاً وجود دارد یا خیر.
  • خط ۱۳: کلاینت فرمان [RCPT TO: <destinataire>] را ارسال می‌کند که آدرس ایمیل گیرنده پیام را مشخص می‌کند.
  • خط ۱۴: سرور SMTP پاسخ می‌دهد که این آدرس را می‌پذیرد. در اینجا نیز یک بررسی نحوی انجام می‌شود.
  • خط ۱۵: کلاینت فرمان [DATA] را ارسال می‌کند که به کاربر نشان می‌دهد خطوط بعدی خود پیام را تشکیل می‌دهند.
  • خط ۱۶: سرور پاسخ می‌دهد که پیام قابل ارسال است. پیام از مجموعه‌ای از خطوط متن تشکیل شده است که باید با خطی حاوی یک کاراکتر واحد به پایان برسد: یک نقطه.
  • خطوط ۱۷–۲۵: پیامی که توسط کلاینت ارسال می‌شود
  • خطوط ۱۷–۱۹: سرآیندهای پیام [From:, To:, Subject:] به ترتیب برای نشان دادن فرستنده، گیرنده و موضوع پیام استفاده می‌شوند.
  • خط ۲۰: یک خط خالی که پایان سرآیندها را نشان می‌دهد
  • خطوط ۲۱–۲۳: متن پیام
  • خط ۲۴: خطی متشکل از یک نقطه، که پایان پیام را نشان می‌دهد.
  • خط ۲۶: سرور SMTP پاسخ می‌دهد که پیام را می‌پذیرد
  • خط ۲۷: کلاینت فرمان [QUIT] را ارسال می‌کند تا نشان دهد که کارش تمام شده است
  • خط ۲۸: سرور SMTP پاسخ می‌دهد که قصد دارد اتصال را با مشتری ببندد

توضیحات کد

ما وارد جزئیات زیاد کد اسکریپت نمی‌شویم، زیرا به طور گسترده توضیح داده شده است.

  • خطوط ۴۸–۸۰: تابع مسئول پردازش فایل [infos.txt] است که حاوی پیام ارسالی به همراه اطلاعات لازم برای ارسال آن می‌باشد. این تابع یک آرایه را بازمی‌گرداند ($erreur, $smtpServer, $expéditeur, $destinataire, $messge) که شامل موارد زیر است:
    • $erreur: یک پیام خطا در صورت وجود، در غیر این صورت خالی.
    • $smtpServer: نام سرور SMTP برای اتصال
    • $expéditeur: آدرس ایمیل فرستنده
    • $destinataire: آدرس ایمیل گیرنده
    • $message: پیامی که باید ارسال شود. علاوه بر متن پیام، ممکن است سربرگ‌ها نیز وجود داشته باشند.
  • خطوط ۸۴–۱۵۷: تابع sendMail مسئول ارسال پیام است. پارامترهای آن به شرح زیر است:
    • $smtpServer: نام سرور SMTP برای اتصال
    • $expéditeur: آدرس ایمیل فرستنده
    • $destinataire: آدرس ایمیل گیرنده
    • $message: پیامی که باید ارسال شود.
    • $verbose: مقدار ۱ نشان می‌دهد که ارتباط با سرور SMTP باید در کنسول ثبت شود.

تابع sendMail یک پیام خطا را بازمی‌گرداند؛ اگر خطایی رخ نداده باشد، خالی است.

  • خط ۸۸: نام ویندوزی رایانه‌ای را که OS روی آن اجرا می‌شود، بازیابی می‌کند.
  • خط ۹۹: ما دیده‌ایم که دیالوگ کلاینت/سرور از این الگو پیروی می‌کند:
    • کلاینت یک دستور را در یک خط ارسال می‌کند
    • پاسخی از سرور در یک یا چند خط
  • خطوط ۱۶۱–۲۰۸: تابع sendCommand پارامترهای زیر را می‌پذیرد:
    • $connexion: کانال TCP / IP که کلاینت را به سرور متصل می‌کند
    • $commande: دستوری که باید از طریق این کانال ارسال شود. پاسخ سرور به این دستور خوانده خواهد شد.
    • $verbose: مقدار 1 نشان می‌دهد که مبادلات با سرور SMTP باید در کنسول نمایش داده شوند.
    • $withRCLF: مقدار ۱ برای آن نشان می‌دهد که کاراکتر پایان خط "\r\n" باید به انتهای دستور اضافه شود
  • خط 173: کلاینت فرمان را ارسال می‌کند
  • خط ۱۸۱: خواندن اولین خط پاسخ سرور SMTP به شکل xxx text یا xxx-text. حالت دوم نشان می‌دهد که سرور خط دیگری برای ارسال دارد. xxx کد خطای ارسال‌شده توسط سرور است.
  • خط ۱۸۸ – بازیابی کد خطا از پاسخ
  • خطوط ۱۹۱–۱۹۹: خواندن سایر خطوط پاسخ
  • خطوط ۲۰۳–۲۰۴: اگر کد خطا >=۵۰۰ باشد، سرور 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]. در پنجرهٔ DOS، دستورات زیر را به ترتیب وارد کنید:

<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

// مدیریت خطا
ini_set("display_errors", "off");
//ماژول‌ها
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";


// کلاینت SMTP (SendMail پروتکل انتقال) برای ارسال یک پیام
//اطلاعات از فایلی به نام $INFOS که شامل خطوط زیر است، گرفته شده است
// خط ۱: smtp, فرستنده, گیرنده, پیوست
// خطوط بعدی: متن پیام
// ارسال‌کننده: ایمیل ارسال‌کننده
//گیرنده: آدرس ایمیل گیرنده
// SMTP: نام سرور SMTP برای استفاده
// پیوست: نام سند برای پیوست کردن
// 
// داده‌ها
$INFOS = "mail2.txt"; //پارامترهای ارسال ایمیل
// بازیابی تنظیمات ایمیل
list($erreur, $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) = getInfos($INFOS);
// خطا؟
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire,$sujet, $attachement]\n";
//ارسال ایمیل در حالت تفصیلی
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
print "Résultat de l'envoi : $résultat\n";
//پایان
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
// اطلاعات را بازمی‌گرداند ($smtp,$expéditeur,$destinataire,$message, $sujet, $attachement) استخراج‌شده از فایل متنی $fichier
// خط ۱: smtp, فرستنده, گیرنده, موضوع, پیوست
// خطوط بعدی: متن پیام
...
//بازگشت
  return array("", $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
}

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

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) {
// ارسال می‌کند $message به سرور SMTP $smtpserver به نمایندگی از $expéditeur
//به $destinataire. سند $attachement به پیام پیوست شده است
// پیام دارای موضوع $sujet است
// 
  //پیام
  $msg = new Mail_Mime();
  $msg->setTXTBody($message);
  $msg->addAttachment($attachement);
  $headers = $msg->headers(array("From" => $expéditeur, "To" => $destinataire, "Subject" => $sujet));
  //ارسال شد
  $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) {
// علامت پایان خط از $ligne در صورت وجود حذف می‌شود
  
}

فایل [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
  • خط ۱: به ترتیب، سرور SMTP، آدرس فرستنده، آدرس گیرنده، موضوع پیام و سند پیوست.
  • خطوط ۲–۴: متن پیام

خروجی صفحه

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 خود با نسخه قبلی متفاوت است. ما این تابع را در زیر توضیح می‌دهیم:

  • خط ۶: اسکریپت‌های PHP از ماژول‌های PEAR در دایرکتوری‌ای نصب شده‌اند که به طور پیش‌فرض توسط تفسیرگر PHP اسکن نمی‌شود. برای اطمینان از اینکه تفسیرگر بتواند ماژول‌های PEAR را پیدا کند، ما به‌صورت دستی دایرکتوری‌هایی را که تفسیرگر PHP باید جستجو کند، مشخص می‌کنیم. امکان تغییر برخی پارامترهای پیکربندی تفسیرگر PHP در زمان اجرا وجود دارد. این تغییر تنها برای اسکریپتی که آن را ایجاد می‌کند قابل مشاهده است و فقط در زمانی که آن اسکریپت در حال اجراست. پیکربندی پیش‌فرض برای تفسیرگر PHP را می‌توان در فایل <PHP_installdir>/PHP.ini یافت. این فایل شامل خطوطی به شکل زیر است
clé=valeur

مقدار این کلید را می‌توان در زمان اجرا توسط تابع ini_set(key, nouvelle_valeur) تغییر داد. کلیدی که توسط تفسیرگر برای مشخص کردن مسیر جستجو برای توابع و کلاس‌های PHP که در اسکریپت به آنها ارجاع داده شده است، استفاده می‌شود، 'include_path' است. در اینجا، ما در مسیر جستجو هم پوشه اسکریپت (.) و هم پوشه PEAR را که در داخل پوشه نصب تفسیرگر PHP قرار دارد، شامل می‌کنیم.

  • خطوط ۷–۹: اسکریپت‌های PHP برای ارسال ایمیل‌ها بارگذاری می‌شوند.
  • خط ۵۰: تابع sendmail که مسئول ارسال ایمیل است. پارامترهای آن به شرح زیر است:
    • $smtpServer: نام سرور SMTP برای اتصال
    • $expéditeur: آدرس ایمیل فرستنده
    • $destinataire: آدرس ایمیل گیرنده
    • $message: پیام ارسالی.
    • $sujet: موضوع پیام
    • $attachement: نام سندی که باید به پیام پیوست شود

تابع sendMail یک پیام خطا را بازمی‌گرداند؛ اگر خطایی رخ نداده باشد، یک پیام خالی بازمی‌گرداند.

  • خط ۵۶: ایجاد یک پیام از نوع Mail_Mime. این پیام شامل سربرگ‌ها (From, To, Subject) و یک بدنه (خود پیام) است.
  • خط ۵۷: بدنه پیام Mail_Mime تنظیم می‌شود.
  • خط ۵۸: یک سند به پیام پیوست شده است
  • خط ۵۹: سربرگ‌های (From, To, Subject) پیام Mail_Mime تنظیم می‌شوند
  • خط ۶۱: کلاس مسئول ارسال پیام Mail_Mime ایجاد می‌شود. پارامتر اول متد نام پروتکلی است که باید استفاده شود، در این مورد پروتکل SMTP. پارامتر دوم آرایه‌ای است که نام و پورت سرویس SMTP مورد استفاده را مشخص می‌کند
  • خط ۶۲: ارسال پیام. متد `send` سه پارامتر می‌گیرد: آدرس فرستنده، سرآیندهای پیام `Mail_Mime` و بدنه پیام `Mail_Mime`. تابع `send` مقدار بولی `TRUE` را در صورت ارسال موفقیت‌آمیز پیام بازمی‌گرداند، و در غیر این صورت یک پیام خطا.