簡單郵件傳輸協議SMTP


1、SMTP是由源地址到目的地址傳送郵件的一組規則,用來控制信件的中轉方式。

2、SMTP服務器是遵循SMTP協議的發送郵件服務器,用來發送或者中轉發出的郵件,客戶端通過SMTP命令與SMTP服務器進行交互。

3、連接和發送郵件步驟如下:

  (1)建立TCP連接;

  (2)客戶端發送HELO命令以標識發件人的身份,服務器以OK作為響應,表明准備接收;

  (3)使用AUTH命令登錄SMTP服務器,輸入用戶名和密碼(用戶名和密碼要用base64進行加密);

  (4)客戶端發送MAIL命令輸入發件人郵箱地址,服務器以OK作為響應;

  (5)客戶端發送RCPT命令,標識該電子郵件的計划接收人,服務器以OK作為響應;

  (6)協商結束后,使用DATA命令發送;

  (7)以"."號表示結束,輸入內容一起發送出去,

  (8)結束此次發送,用QUIT命令退出。

  下面給出一個使用telnet創建一個smtp會話的例子

  注意:上述命令不一定一次性成功,服務器可能會返回錯誤響應,如上圖,我輸入了很多次才成功的

4、上面我們進行了SMTP連接和發送,接下來我們認識下SMTP協議的常用命令

  DATA:開始信息寫作

  EXPN:驗證給定的郵箱列表是否存在,擴充郵箱列表,常被禁用

  HELO:向服務器標識用戶身份,返回郵件服務器身份

  HELP:查詢服務器支持什么命令,返回命令中的信息

  MAIL FROM:在主機上初始化一個郵件回話

  NOOP:無操作,服務器響應OK

  QUIT:終止郵件會話

  RCPT TO:標識單個的郵件接收人,MAIL命令后面可以有多個RCPT TO

  RSET:重置會話,當前傳輸被取消

  SAML FROM:發送郵件到用戶終端和郵箱

  SEND FROM:發送郵件到用戶終端

  SOML FROM:發送郵件到用戶終端或郵箱

  TURN:接收端和發送端交換角色

 

5、下面我們看一個用socket發送郵件的例子,看完這個例子,基本上能理解清楚SMTP是如何發郵件的

  首先,我們先來認識一個函數

  fsockopen($hostname, $port, [$errno], [$errstr], [$timeout]);

    $hostname:要連接的服務器路徑

    $port:要綁定的端口

    $errno:保存連接發生錯誤時的錯誤代號

    $errstr:保存錯誤信息

    $timeout:設置連接的超時時間,單位為秒

 

先創建一個smtp.class.php類

  1 <?php
  2 
  3 class smtp_email
  4 {
  5     private $host;                    //保存要連接的smtp服務器
  6     private $port;                    //要綁定的端口,默認為25
  7     private $user;                    //要登錄SMTP服務器的用戶名
  8     private $pass;                    //要登錄SMTP服務器的密碼
  9     private $debug = false;        //標識是都開啟調試模式,默認關閉
 10     private $sock;                    //保存與SMTP服務器連接的句柄
 11     private $mail_format = 0;        //表示使用什么格式發送郵件,0位普通文本,1為HTML郵件
 12 
 13     //初始化
 14     public function __construct($host, $port, $user, $pass, $format = 1, $debug = 0)
 15     {
 16         $this->host = $host;
 17         $this->port = $port;
 18         $this->user = base64_encode($user);
 19         $this->pass = base64_encode($pass);
 20         $this->mail_format = $format;
 21         $this->debug = $debug;
 22 
 23         $this->sock = fsockopen($this->host, $this->port, &$errno, &$errstr, 10);    //使用fsockopen()連接服務器
 24 
 25         if (!$this->sock) {
 26             exit("Error Number:$errno, Error Message:$errstr");
 27         }
 28 
 29         $response = fgets($this->sock);                    //獲取服務器信息
 30         if (strstr($response, "220") == false) {
 31             exit("server error:$response\n");
 32         }
 33     }
 34 
 35     //根據用戶是否開啟調試模式顯示調試信息
 36     private function show_debug($message)
 37     {
 38         if ($this->debug) {
 39             echo "<p>Debug:$message</p>\n";
 40         }
 41     }
 42 
 43     //把命令發送到服務器中執行,然后取的服務器的反饋信息
 44     private function do_command($cmd, $return_code)
 45     {
 46         fwrite($this->sock, $cmd);
 47 
 48         $response = fgets($this->sock);
 49         if (strstr($response, $return_code) == false) {
 50             $this->show_debug($response);
 51             return false;
 52         }
 53 
 54         return true;
 55     }
 56 
 57     //驗證郵箱地址是否合法
 58     private function is_email($email)
 59     {
 60         $pattern = '/^[^_][\w]*@[\w.]+[\w]*[^_]$/';
 61         if (preg_match_all($pattern, $email, $matches)) {
 62             return true;
 63         } else {
 64             return false;
 65         }
 66     }
 67 
 68     //發送郵件  $from:發件人email   $to:收件人email    $subject:郵件主題   $body:郵件內容
 69     public function send_email($from, $to, $subject, $body)
 70     {
 71         if (!$this->is_email($from) || !$this->is_email($to)) {
 72             $this->show_debug("please enter vaild from/to email.");
 73             return false;
 74         }
 75 
 76         if (empty($subject) || empty($body)) {
 77             $this->show_debug("please enter subject/content.");
 78             return false;
 79         }
 80 
 81         $detail = "From:{$from}\r\n";
 82         $detail .= "To:{$to}\r\n";
 83         $detail .= "Subject:{$subject}\r\n";
 84 
 85         if ($this->mail_format == 1) {
 86             $detail .= "Content-Type:text/html;\r\n";
 87         } else {
 88             $detail .= "Content-Type:text/plain;\r\n";
 89         }
 90 
 91         $detail .="charset = gb2312\r\n\r\n" ;
 92         $detail .= "$body";
 93 
 94         $this->do_command("HELO smtp.qq.com\r\n", 250);
 95         $this->do_command("AUTH LOGIN\r\n", 334);
 96         $this->do_command($this->user."\r\n", 334);
 97         $this->do_command($this->pass."\r\n", 235);
 98         $this->do_command("MAIL FROM:<".$from.">\r\n", 250);
 99         $this->do_command("RCPT TO<".$to.">\r\n", 250);
100         $this->do_command("DATA\r\n", 354);
101         $this->do_command($detail."\r\n.\r\n", 250);
102         $this->do_command("QUIT\r\n", 221);
103 
104         return true;
105     }
106 }
107 
108 
109 ?>

 

接着創建一個sendEmail.php測試文件進行測試

 1 <?php
 2 
 3     include("smtp.class.php");
 4 
 5     $host = "smtp.163.com";
 6     $port = 25;
 7     $user = "onedream_kelly@163.com";
 8     $pass = "**********";
 9 
10     $from = "onedream_kelly@163.com";
11     $to = "****@163.com";
12     $subject = "記得收衣服啊";
13     $content = "今天我不回家,你記得收到衣服,免得到時衣服淋濕了沒得穿";
14 
15     $mail = new smtp_email($host, $port, $user, $pass, 1);
16     $res = $mail->send_email($from, $to, $subject, $content);
17     if ($res == true) {
18         echo "send success";
19     } else {
20         echo "send fail";
21     }
22 ?>

發送成功!

 

其實,現成有一個比較有名氣的郵件類,Emailer,大家可以看看這個是如何實現郵件發送和郵件接收的,理解清楚了,基本上會應用此來發送郵件了。

 

接下來我們思考一個問題:PHP與C語言怎么交互呢??

  你可能會想到用C語言寫擴展,或則使用exec、system等命令,但我們可以換一個思路,就是用C語言提供服務,用PHP請求這個服務,PHP就能借助C語言完成很多看似不能完成的任務了。現在流行的WebGame正是利用C語言、java等重量級語言在底層完成復雜的運算,通過Socket把接口提供給PHP使用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM