前面介绍了预定义的变量和对邮件元素的处理,下面继续代码的最后一部分:连接服务器、发送邮件。
PHP代码
- if(!$fp = fsockopen($set['server'], $set['port'], $errno, $errstr, 30)) {
- return false;
- }
- stream_set_blocking($fp, true);
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != '220') {
- return false;
- }
上面是连接服务器的代码,要求服务器返回以220开头的指令。
bool stream_set_blocking ( resource $stream , int $mode )函数,戒烟如你也是第一次遇到,查了下资料,该函数是设置数据流阻塞模式,mode 如果为1或TRUE,则为块模式,等待数据满足要求,防止数据没有读完就退出。
PHP代码
- fputs($fp, ($set['auth'] ? 'EHLO' : 'HELO')." HuBing\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250) {
- return false;
- }
- while(1) {
- if(substr($lastmessage, 3, 1) != '-' || emptyempty($lastmessage)) {
- break;
- }
- $lastmessage = fgets($fp, 512);
- }
这里说一下第一行的EHLO和HELO,这是开始SMTP会话的指令,前者要求身份验证,后者不需要。
PHP代码
- if($set['auth']) {
- fputs($fp, "AUTH LOGIN\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 334) {
- return false;
- }
- fputs($fp, base64_encode($set['username'])."\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 334) {
- return false;
- }
- fputs($fp, base64_encode($set['password'])."\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 235) {
- return false;
- }
- }
如果需要身份验证,则向服务器发送用户名和密码,请求验证。
PHP代码
- fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $set['from']).">\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 250) {
- fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $set['from']).">\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 250) {
- return false;
- }
- }
- $email_tos = array();
- foreach(explode(',', $mail['to']) as $touser) {
- $touser = trim($touser);
- if($touser) {
- fputs($fp, "RCPT TO: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser).">\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 250) {
- fputs($fp, "RCPT TO: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser).">\r\n");
- $lastmessage = fgets($fp, 512);
- if (substr($lastmessage, 0, 3) != 250) {
- return false;
- }
- }
- }
- }
向服务器发送发件人和收件人信息,注意一下,这里每次发送都进行了两次测试,一次不成功就再来一次。
PHP代码
- fputs($fp, "DATA\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 354) {
- return false;
- }
告诉SMTP服务器邮件正文开始了,服务器返回354指令,那就继续吧!
PHP代码
- $headers .= 'Message-ID: <'.gmdate('YmdHs').'.'.substr(md5($mail['message'].
- microtime()), 0, 6).rand(100000, 999999).'@'.$_SERVER['HTTP_HOST'].
- '>'.$delimiter;
- fputs($fp, "Date: ".gmdate('r')."\r\n");
- fputs($fp, "To: ".$mail['to']."\r\n");
- fputs($fp, "Subject: ".$mail['subject']."\r\n");
- fputs($fp, $headers."\r\n");
- fputs($fp, "\r\n\r\n");
- fputs($fp, $mail['message']."\r\n.\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 250) {
- return false;
- }
第一行向邮件头部添加了一个Message-ID的东东,然后就逐一发送发件时间、收件人、主题、邮件头、正文,发邮件的过程到此结束,下面是发送退出指令了。
PHP代码
- fputs($fp, "QUIT\r\n");
- return true;
到此结束。

