PHP编程:PHP实现支持SSL连接的SMTP邮件发送类
发布时间:2020-12-13 02:26:50 所属栏目:PHP教程 来源:网络整理
导读:《PHP实现支持SSL连接的SMTP邮件发送类》要点: 本文介绍了PHP实现支持SSL连接的SMTP邮件发送类,希望对您有用。如果有疑问,可以联系我们。 PHP实例 本篇章节讲解PHP实现支持SSL连接的SMTP邮件发送类.供大家参考研究.具体如下: PHP实例 该实例代码
《PHP实现支持SSL连接的SMTP邮件发送类》要点: PHP实例本篇章节讲解PHP实现支持SSL连接的SMTP邮件发送类.分享给大家供大家参考.具体如下: PHP实例该实例代码测试过了gmail和QQ邮箱的SMTP.具体代码如下:
代码如下:
<?php
/** * 邮件发送类 * 支持发送纯文本邮件和HTML格式的邮件,可以多收件人,多抄送,多秘密抄送,带附件(单个或多个附件),支持到服务器的ssl连接 * 需要的php扩展:sockets、Fileinfo和openssl. * 编码格式是UTF-8,传输编码格式是base64 * @example * $mail = new MySendMail(); * $mail->setServer("smtp@126.com","XXXXX@126.com","XXXXX"); //设置smtp服务器,普通连接方式 * $mail->setServer("smtp.gmail.com","XXXXX@gmail.com","XXXXX",465,true); //设置smtp服务器,到服务器的SSL连接 * $mail->setFrom("XXXXX"); //设置发件人 * $mail->setReceiver("XXXXX"); //设置收件人,多个收件人,调用多次 * $mail->setCc("XXXX"); //设置抄送,多个抄送,调用多次 * $mail->setBcc("XXXXX"); //设置秘密抄送,多个秘密抄送,调用多次 * $mail->addAttachment("XXXX"); //添加附件,多个附件,调用多次 * $mail->setMail("test","<b>test</b>"); //设置邮件主题、内容 * $mail->sendMail(); //发送 */ class MySendMail { ??? /** ??? * @var string 邮件传输代理用户名 ??? * @access protected ??? */ ??? protected $_userName; ??? /** ??? * @var string 邮件传输代理密码 ??? * @access protected ??? */ ??? protected $_password; ??? /** ??? * @var string 邮件传输代理服务器地址 ??? * @access protected ??? */ ??? protected $_sendServer; ??? /** ??? * @var int 邮件传输代理服务器端口 ??? * @access protected ??? */ ??? protected $_port; ??? /** ??? * @var string 发件人 ??? * @access protected ??? */ ??? protected $_from; ??? /** ??? * @var array 收件人 ??? * @access protected ??? */ ??? protected $_to = array(); ??? /** ??? * @var array 抄送 ??? * @access protected ??? */ ??? protected $_cc = array(); ??? /** ??? * @var array 秘密抄送 ??? * @access protected ??? */ ??? protected $_bcc = array(); ??? /** ??? * @var string 主题 ??? * @access protected ??? */ ??? protected $_subject; ??? /** ??? * @var string 邮件正文 ??? * @access protected ??? */ ??? protected $_body; ??? /** ??? * @var array 附件 ??? * @access protected ??? */ ??? protected $_attachment = array(); ??? /** ??? * @var reource socket资源 ??? * @access protected ??? */ ??? protected $_socket; ??? /** ??? * @var reource 是否是平安连接 ??? * @access protected ??? */ ??? protected $_isSecurity; ??? /** ??? * @var string 错误信息 ??? * @access protected ??? */ ??? protected $_errorMessage; ??? /** ??? * 设置邮件传输代理,如果是可以匿名发送有邮件的服务器,只需传递代理服务器地址就行 ??? * @access public ??? * @param string $server 代理服务器的ip或者域名 ??? * @param string $username 认证账号 ??? * @param string $password 认证密码 ??? * @param int $port 代理服务器的端口,smtp默认25号端口 ??? * @param boolean $isSecurity 到服务器的连接是否为平安连接,默认false ??? * @return boolean ??? */ ??? public function setServer($server,$username="",$password="",$port=25,$isSecurity=false) { ??????? $this->_sendServer = $server; ??????? $this->_port = $port; ??????? $this->_isSecurity = $isSecurity; ??????? $this->_userName = empty($username) ? "" : base64_encode($username); ??????? $this->_password = empty($password) ? "" : base64_encode($password); ??????? return true; ??? } ??? /** ??? * 设置发件人 ??? * @access public ??? * @param string $from 发件人地址 ??? * @return boolean ??? */ ??? public function setFrom($from) { ??????? $this->_from = $from; ??????? return true; ??? } ??? /** ??? * 设置收件人,调用多次. ??? * @access public ??? * @param string $to 收件人地址 ??? * @return boolean ??? */ ??? public function setReceiver($to) { ??????? $this->_to[] = $to; ??????? return true; ??? } ??? /** ??? * 设置抄送,调用多次. ??? * @access public ??? * @param string $cc 抄送地址 ??? * @return boolean ??? */ ??? public function setCc($cc) { ??????? $this->_cc[] = $cc; ??????? return true; ??? } ??? /** ??? * 设置秘密抄送,调用多次 ??? * @access public ??? * @param string $bcc 秘密抄送地址 ??? * @return boolean ??? */ ??? public function setBcc($bcc) { ??????? $this->_bcc[] = $bcc; ??????? return true; ??? } ??? /** ??? * 设置邮件附件,调用多次 ??? * @access public ??? * @param string $file 文件地址 ??? * @return boolean ??? */ ??? public function addAttachment($file) { ??????? if(!file_exists($file)) { ??????????? $this->_errorMessage = "file " . $file . " does not exist."; ??????????? return false; ??????? } ??????? $this->_attachment[] = $file; ??????? return true; ??? } ??? /** ??? * 设置邮件信息 ??? * @access public ??? * @param string $body 邮件主题 ??? * @param string $subject 邮件主体内容,可以是纯文本,也可是是HTML文本 ??? * @return boolean ??? */ ??? public function setMail($subject,$body) { ??????? $this->_subject = base64_encode($subject); ??????? $this->_body = base64_encode($body); ??????? return true; ??? } ??? /** ??? * 发送邮件 ??? * @access public ??? * @return boolean ??? */ ??? public function sendMail() { ??????? $command = $this->getCommand(); ??????? $this->_isSecurity ? $this->socketSecurity() : $this->socket(); ??????? foreach ($command as $value) { ??????????? $result = $this->_isSecurity ? $this->sendCommandSecurity($value[0],$value[1]) : $this->sendCommand($value[0],$value[1]); ??????????? if($result) { ??????????????? continue; ??????????? } ??????????? else{ ??????????????? return false; ??????????? } ??????? } ??????? //其实这里也没必要关闭,smtp命令:QUIT发出之后,服务器就关闭了连接,本地的socket资源会自动释放 ??????? $this->_isSecurity ? $this->closeSecutity() : $this->close(); ??????? return true; ??? } ??? /** ??? * 返回错误信息 ??? * @return string ??? */ ??? public function error(){ ??????? if(!isset($this->_errorMessage)) { ??????????? $this->_errorMessage = ""; ??????? } ??????? return $this->_errorMessage; ??? } ??? /** ??? * 返回mail命令 ??? * @access protected ??? * @return array ??? */ ??? protected function getCommand() { ??????? $separator = "----=_Part_" . md5($this->_from . time()) . uniqid(); //分隔符 ??????? $command = array( ??????????????? array("HELO sendmailrn",250) ??????????? ); ??????? if(!empty($this->_userName)){ ??????????? $command[] = array("AUTH LOGINrn",334); ??????????? $command[] = array($this->_userName . "rn",334); ??????????? $command[] = array($this->_password . "rn",235); ??????? } ??????? //设置发件人 ??????? $command[] = array("MAIL FROM: <" . $this->_from . ">rn",250); ??????? $header = "FROM: <" . $this->_from . ">rn"; ??????? //设置收件人 ??????? if(!empty($this->_to)) { ??????????? $count = count($this->_to); ??????????? if($count == 1){ ??????????????? $command[] = array("RCPT TO: <" . $this->_to[0] . ">rn",250); ??????????????? $header .= "TO: <" . $this->_to[0] .">rn"; ??????????? } ??????????? else{ ??????????????? for($i=0; $i<$count; $i++){ ??????????????????? $command[] = array("RCPT TO: <" . $this->_to[$i] . ">rn",250); ??????????????????? if($i == 0){ ??????????????????????? $header .= "TO: <" . $this->_to[$i] .">"; ??????????????????? } ??????????????????? elseif($i + 1 == $count){ ??????????????????????? $header .= ",<" . $this->_to[$i] .">rn"; ??????????????????? } ??????????????????? else{ ??????????????????????? $header .= ",<" . $this->_to[$i] .">"; ??????????????????? } ??????????????? } ??????????? } ??????? } ??????? //设置抄送 ??????? if(!empty($this->_cc)) { ??????????? $count = count($this->_cc); ??????????? if($count == 1){ ??????????????? $command[] = array("RCPT TO: <" . $this->_cc[0] . ">rn",250); ??????????????? $header .= "CC: <" . $this->_cc[0] .">rn"; ??????????? } ??????????? else{ ??????????????? for($i=0; $i<$count; $i++){ ??????????????????? $command[] = array("RCPT TO: <" . $this->_cc[$i] . ">rn",250); ??????????????????? if($i == 0){ ??????????????????? $header .= "CC: <" . $this->_cc[$i] .">"; ??????????????????? } ??????????????????? elseif($i + 1 == $count){ ??????????????????????? $header .= ",<" . $this->_cc[$i] .">rn"; ??????????????????? } ??????????????????? else{ ??????????????????????? $header .= ",<" . $this->_cc[$i] .">"; ??????????????????? } ??????????????? } ??????????? } ??????? } ??????? //设置秘密抄送 ??????? if(!empty($this->_bcc)) { ??????????? $count = count($this->_bcc); ??????????? if($count == 1) { ??????????????? $command[] = array("RCPT TO: <" . $this->_bcc[0] . ">rn",250); ??????????????? $header .= "BCC: <" . $this->_bcc[0] .">rn"; ??????????? } ??????????? else{ ??????????????? for($i=0; $i<$count; $i++){ ??????????????????? $command[] = array("RCPT TO: <" . $this->_bcc[$i] . ">rn",250); ??????????????????? if($i == 0){ ??????????????????? $header .= "BCC: <" . $this->_bcc[$i] .">"; ??????????????????? } ??????????????????? elseif($i + 1 == $count){ ??????????????????????? $header .= ",<" . $this->_bcc[$i] .">rn"; ??????????????????? } ??????????????????? else{ ??????????????????????? $header .= ",<" . $this->_bcc[$i] .">"; ??????????????????? } ??????????????? } ??????????? } ??????? } ??????? //主题 ??????? $header .= "Subject: =?UTF-8?B?" . $this->_subject ."?=rn"; ??????? if(isset($this->_attachment)) { ??????????? //含有附件的邮件头需要声明成这个 ??????????? $header .= "Content-Type: multipart/mixed;rn"; ??????? } ??????? elseif(false){ ??????????? //邮件体含有图片资源的,且包含的图片在邮件内部时声明成这个,如果是引用的远程图片,就不需要了 ??????????? $header .= "Content-Type: multipart/related;rn"; ??????? } ??????? else{ ??????????? //html或者纯文本的邮件声明成这个 ??????????? $header .= "Content-Type: multipart/alternative;rn"; ??????? } ??????? //邮件头分隔符 ??????? $header .= "t" . 'boundary="' . $separator . '"'; ??????? $header .= "rnMIME-Version: 1.0rn"; ??????? //这里开始是邮件的body部分,body部分分成几段发送 ??????? $header .= "rn--" . $separator . "rn"; ??????? $header .= "Content-Type:text/html; charset=utf-8rn"; ??????? $header .= "Content-Transfer-Encoding: base64rnrn"; ??????? $header .= $this->_body . "rn"; ??????? $header .= "--" . $separator . "rn"; ??????? //加入附件 ??????? if(!empty($this->_attachment)){ ??????????? $count = count($this->_attachment); ??????????? for($i=0; $i<$count; $i++){ ??????????????? $header .= "rn--" . $separator . "rn"; ??????????????? $header .= "Content-Type: " . $this->getMIMEType($this->_attachment[$i]) . '; name="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' . "rn"; ??????????????? $header .= "Content-Transfer-Encoding: base64rn"; ??????????????? $header .= 'Content-Disposition: attachment; filename="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' . "rn"; ??????????????? $header .= "rn"; ??????????????? $header .= $this->readFile($this->_attachment[$i]); ??????????????? $header .= "rn--" . $separator . "rn"; ??????????? } ??????? } ??????? //结束邮件数据发送 ??????? $header .= "rn.rn"; ? ??????? $command[] = array("DATArn",354); ??????? $command[] = array($header,250); ??????? $command[] = array("QUITrn",221); ??????? return $command; ??? } ??? /** ??? * 发送命令 ??? * @access protected ??? * @param string $command 发送到服务器的smtp命令 ??? * @param int $code 期望服务器返回的响应吗 ??? * @return boolean ??? */ ??? protected function sendCommand($command,$code) { ??????? echo 'Send command:' . $command . ',expected code:' . $code . '<br />'; ??????? //发送命令给服务器 ??????? try{ ??????????? if(socket_write($this->_socket,$command,strlen($command))){ ??????????????? //当邮件内容分多次发送时,没有$code,服务器没有返回 ??????????????? if(empty($code))? { ??????????????????? return true; ??????????????? } ??????????????? //读取服务器返回 ??????????????? $data = trim(socket_read($this->_socket,1024)); ??????????????? echo 'response:' . $data . '<br /><br />'; ??????????????? if($data) { ??????????????????? $pattern = "/^".$code."+?/"; ??????????????????? if(preg_match($pattern,$data)) { ??????????????????????? return true; ??????????????????? } ??????????????????? else{ ??????????????????????? $this->_errorMessage = "Error:" . $data . "|**| command:"; ??????????????????????? return false; ??????????????????? } ??????????????? } ??????????????? else{ ??????????????????? $this->_errorMessage = "Error:" . socket_strerror(socket_last_error()); ??????????????????? return false; ??????????????? } ??????????? } ??????????? else{ ??????????????? $this->_errorMessage = "Error:" . socket_strerror(socket_last_error()); ??????????????? return false; ??????????? } ??????? }catch(Exception $e) { ??????????? $this->_errorMessage = "Error:" . $e->getMessage(); ??????? } ??? } ??? /** ??? * 平安连接发送命令 ??? * @access protected ??? * @param string $command 发送到服务器的smtp命令 ??? * @param int $code 期望服务器返回的响应吗 ??? * @return boolean ??? */ ??? protected function sendCommandSecurity($command,expected code:' . $code . '<br />'; ??????? try { ??????????? if(fwrite($this->_socket,$command)){ ??????????????? //当邮件内容分多次发送时,服务器没有返回 ??????????????? if(empty($code))? { ??????????????????? return true; ??????????????? } ??????????????? //读取服务器返回 ??????????????? $data = trim(fread($this->_socket,$data)) { ??????????????????????? return true; ??????????????????? } ??????????????????? else{ ??????????????????????? $this->_errorMessage = "Error:" . $data . "|**| command:"; ??????????????????????? return false; ??????????????????? } ??????????????? } ??????????????? else{ ??????????????????? return false; ??????????????? } ??????????? } ??????????? else{ ??????????????? $this->_errorMessage = "Error: " . $command . " send failed"; ??????????????? return false; ??????????? } ??????? }catch(Exception $e) { ??????????? $this->_errorMessage = "Error:" . $e->getMessage(); ??????? } ??? } ??? /** ??? * 读取附件文件内容,返回base64编码后的文件内容 ??? * @access protected ??? * @param string $file 文件 ??? * @return mixed ??? */ ??? protected function readFile($file) { ??????? if(file_exists($file)) { ??????????? $file_obj = file_get_contents($file); ??????????? return base64_encode($file_obj); ??????? } ??????? else { ??????????? $this->_errorMessage = "file " . $file . " dose not exist"; ??????????? return false; ??????? } ??? } ??? /** ??? * 获取附件MIME类型 ??? * @access protected ??? * @param string $file 文件 ??? * @return mixed ??? */ ??? protected function getMIMEType($file) { ??????? if(file_exists($file)) { ??????????? $mime = mime_content_type($file); ??????????? /*if(! preg_match("/gif|jpg|png|jpeg/",$mime)){ ??????????????? $mime = "application/octet-stream"; ??????????? }*/ ??????????? return $mime; ??????? } ??????? else { ??????????? return false; ??????? } ??? } ??? /** ??? * 建立到服务器的网络连接 ??? * @access protected ??? * @return boolean ??? */ ??? protected function socket() { ??????? //创建socket资源 ??????? $this->_socket = socket_create(AF_INET,SOCK_STREAM,getprotobyname('tcp')); ??????? if(!$this->_socket) { ??????????? $this->_errorMessage = socket_strerror(socket_last_error()); ??????????? return false; ??????? } ??????? socket_set_block($this->_socket);//设置阻塞模式 ??????? //连接服务器 ??????? if(!socket_connect($this->_socket,$this->_sendServer,$this->_port)) { ??????????? $this->_errorMessage = socket_strerror(socket_last_error()); ??????????? return false; ??????? } ??????? $str = socket_read($this->_socket,1024); ??????? if(!preg_match("/220+?/",$str)){ ??????????? $this->_errorMessage = $str; ??????????? return false; ??????? } ??????? return true; ??? } ??? /** ??? * 建立到服务器的SSL网络连接 ??? * @access protected ??? * @return boolean ??? */ ??? protected function socketSecurity() { ??????? $remoteAddr = "tcp://" . $this->_sendServer . ":" . $this->_port; ??????? $this->_socket = stream_socket_client($remoteAddr,$errno,$errstr,30); ??????? if(!$this->_socket){ ??????????? $this->_errorMessage = $errstr; ??????????? return false; ??????? } ??????? //设置加密连接,默认是ssl,如果需要tls连接,可以查看php手册stream_socket_enable_crypto函数的解释 ??????? stream_socket_enable_crypto($this->_socket,true,STREAM_CRYPTO_METHOD_SSLv23_CLIENT); ??????? stream_set_blocking($this->_socket,1); //设置阻塞模式 ??????? $str = fread($this->_socket,$str)){ ??????????? $this->_errorMessage = $str; ??????????? return false; ??????? } ??????? return true; ??? } ??? /** ??? * 关闭socket ??? * @access protected ??? * @return boolean ??? */ ??? protected function close() { ??????? if(isset($this->_socket) && is_object($this->_socket)) { ??????????? $this->_socket->close(); ??????????? return true; ??????? } ??????? $this->_errorMessage = "No resource can to be close"; ??????? return false; ??? } ??? /** ??? * 关闭平安socket ??? * @access protected ??? * @return boolean ??? */ ??? protected function closeSecutity() { ??????? if(isset($this->_socket) && is_object($this->_socket)) { ??????????? stream_socket_shutdown($this->_socket,STREAM_SHUT_WR); ??????????? return true; ??????? } ??????? $this->_errorMessage = "No resource can to be close"; ??????? return false; ??? } } PHP实例希望本文所述对大家的php程序设计有所帮助. 欢迎参与《PHP实现支持SSL连接的SMTP邮件发送类》讨论,分享您的想法,编程之家 52php.cn为您提供专业教程。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |