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 = "[email protected]"; 8 $pass = "**********"; 9 10 $from = "[email protected]"; 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使用。