123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- <?php
- /**
- * SMTP邮件发送类
- * 来源: uhome:http://u.discuz.net/
- * 目录: source/function_sendmail.php
- * 改造: 改成类的方式,增加对tls的支持,增加socket超时控制,去除多余配置
- * 对tls的支持要加上openssl扩展.可以用程序判断: in_array('ssl',stream_get_transports()) ? 'Yes' : 'No!'
- * oo::smtp()->send('zjmaslow@gmail.com,zjmaslow@126.com,ColinZhou@boyaa.com', '我是邮件标题', '我是邮件内容');
- */
- class smtp{
- public $tls = true; //是否是tls服务器.不是请改成false
- public $server = 'mail.boyaa.com'; //服务器地址.GMail为:ssl://smtp.gmail.com:465 且socket要支持ssl:in_array('ssl',stream_get_transports()) 如果是tls则此处填服务器地址(无需tls://)并把$tls设为true
- public $port = '587'; //服务器端口
- public $auth = true; //smtp服务器是否需要验证
- public $user = 'noreply-game@boyaa.com'; //SMTP用户名
- public $password = 'Dd@12wZ#r5'; //SMTP密码
- public $from = 'noreply-game@boyaa.com'; //回复邮箱地址,126的强制跟$user相同,gmail的可以不同
- public $mailer = "boyaa.com"; //客户端标志
- public $errno = 0; //错误代码
- public $errstr = ''; //错误信息
-
- public function __construct(){
- // $this->server = '113.105.73.52'; //境外用另一个邮件服务器
- $this->server = 'mail1.boyaa.com'; //境外用另一个邮件服务器
- if (defined('PRODUCTION_SERVER') && PRODUCTION_SERVER == false) {
- $this->server = 'mail.boyaa.com'; // 内网用内网的邮件服务器
- }
- }
-
- /**
- * 发送邮件
- * @param String $sMails 收件人邮件地址,如果有多个则以,号隔开
- * @param String $sSubject 邮件主题
- * @param String $sMsg 邮件正文内容.支持HTML格式
- * @param String $sFrom 发送者名称.用于对方收件箱中显示
- */
- public function send($sMails, $sSubject, $sMsg, $sFrom='Boyaa-9K'){
-
- $fromuser = strlen( $sFrom) ? '=?utf-8?B?'.base64_encode( $sFrom)."?= <{$this->from}>" : $this->from; //自定义发送者名字
-
- foreach(explode(',', $sMails) as $touser) {
- $tousers[] = preg_match('/^(.+?) \<(.+?)\>$/', $touser, $to) ? '=?utf-8?B?'.base64_encode($to[1])."?= <$to[2]>" : $touser; //使得支持: 接收人名字<***@***.com> 地址形式
- }
- $sHeader = "From: {$fromuser}\r\nX-Priority: 3\r\nX-Mailer: {$this->mailer}!\r\nMIME-Version: 1.0\r\nContent-type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n";
- $sHeader .= 'Message-ID: <'.gmdate('YmdHs').'.'.substr(md5($sMsg.microtime()), 0, 6).rand(100000, 999999).'@'.$_SERVER['HTTP_HOST'].">\r\n";
- $sMails = implode(',', $tousers);
- $sSubject = '=?utf-8?B?'.base64_encode(str_replace("\r", '', str_replace("\n", '', $sSubject))).'?=';
- $sMsg = chunk_split(base64_encode(str_replace("\r\n.", " \r\n..", str_replace("\n", "\r\n", str_replace("\r", "\n", str_replace("\r\n", "\n", str_replace("\n\r", "\r", $sMsg)))))));
-
- if(! $fp = fsockopen($this->server, $this->port, $errno, $errstr, 5)) { //5秒链接超时
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$errstr);
- return false;
- }
-
- stream_set_timeout($fp, 5, 0); //读写操作不能超过5秒
- stream_set_blocking($fp, true);
-
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != '220') {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
-
- fputs($fp, ($this->auth ? 'EHLO' : 'HELO')." {$this->mailer}\r\n");
-
- $lastmessage = fgets($fp, 512);
- if( ! in_array( $errno = substr($lastmessage, 0, 3), array(220, 250))) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- while(1) {
- if(substr($lastmessage, 3, 1) != '-' || empty($lastmessage)) {
- break;
- }
- $lastmessage = fgets($fp, 512);
- }
-
- if( $this->auth) {
- if( $this->tls){
- fputs($fp, "STARTTLS\r\n");
- $lastmessage = fgets($fp, 512);
- if(($errno = substr($lastmessage, 0, 3)) != 220) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- if(! stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
- list($this->errno, $this->errstr) = array($errno, __LINE__);
- return false;
- }
-
- fputs($fp, ($this->auth ? 'HELO' : 'EHLO')." ".$this->mailer."\r\n"); //HELO是EHLO的扩展,支持验证的
-
- $lastmessage = fgets($fp, 512);
- if(($errno = substr($lastmessage, 0, 3)) != 250) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- }
- fputs($fp, "AUTH LOGIN\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 334) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- fputs($fp, base64_encode( $this->user)."\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 334) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
-
- fputs($fp, base64_encode( $this->password)."\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 235) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- }
-
- fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $fromuser).">\r\n");
- $lastmessage = fgets($fp, 512);
- if(substr($lastmessage, 0, 3) != 250) {
- fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $fromuser).">\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 250) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- }
-
- $email_tos = array();
- foreach(explode(',', $sMails) as $touser) {
- $touser = trim($touser);
- if($touser) {
- fputs($fp, "RCPT TO: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser).">\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 250) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
- }
- }
-
- fputs($fp, "DATA\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 354) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
-
- fputs($fp, "Date: ".gmdate('r')."\r\n");
- fputs($fp, "To: ".$sMails."\r\n");
- fputs($fp, "Subject: ".$sSubject."\r\n");
- fputs($fp, $sHeader."\r\n");
- fputs($fp, "\r\n\r\n");
- fputs($fp, "$sMsg\r\n.\r\n");
- $lastmessage = fgets($fp, 512);
- if( ($errno = substr($lastmessage, 0, 3)) != 250) {
- list($this->errno, $this->errstr) = array($errno, __LINE__.':'.$lastmessage);
- return false;
- }
-
- fputs($fp, "QUIT\r\n");
- fclose($fp);
- return true;
- }
- }
|