设为首页 收藏本站
查看: 646|回复: 0

[经验分享] PHP SMTP邮件发送类,支持SSL连接

[复制链接]

尚未签到

发表于 2015-12-24 08:22:41 | 显示全部楼层 |阅读模式
sendmail.sh:
curl -o /tmp/email -s -d "smtp=${SMTP}" -d "from=${FROM}" -d "user=${USER}" -d "pass=${PASS}" -d "to=${TO}" -d "title=${TITLE}" -d "content=${CONTENT}" -d "ssl=${SSL}" -d "port=${PORT}" http://127.0.0.1/mail.php
curl 用法:http://blog.iyunv.com/uid-29110326-id-4818236.html

有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值
下表中列出了一些URL特殊符号及编码:
十六进制值
1.+URL 中+号表示空格%2B
2.空格URL中的空格可以用+号或者编码%20
3./分隔目录和子目录%2F
4.?分隔实际的 URL 和参数%3F
5.%指定特殊字符%25
6.#表示书签%23
7.&URL 中指定的参数间的分隔符%26
8.=URL 中指定参数的值%3D

C++ 替换string中的字符:



  • string& command::replace_all(string& str,const string& old_value,const string& new_value)

  • {
  •     while(true){
  •         string::size_type   pos(0);
  •         if( (pos=str.find(old_value))!=string::npos )
  •             str.replace(pos,old_value.length(),new_value);
  •         else break;
  •     }

  •     return  str;
  • }


  • content = replace_all(content,"&","%26");//URL特殊符号及编码




  点击(此处)折叠或打开


  • 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", "test"); //设置邮件主题、内容
  • * $mail->sendMail(); //发送
  • */

  • if(isset($_REQUEST['smtp']))
  • {
  •     $SMTP=$_REQUEST['smtp'];
  • }
  • if(isset($_REQUEST['from']))
  • {
  •     $FROM=$_REQUEST['from'];
  • }
  • if(isset($_REQUEST['user']))
  • {
  •     $USER=$_REQUEST['user'];
  • }
  • if(isset($_REQUEST['pass']))
  • {
  •     $PASS=$_REQUEST['pass'];
  • }
  • if(isset($_REQUEST['to']))
  • {
  •     $TO=$_REQUEST['to'];
  • }
  • if(isset($_REQUEST['title']))
  • {
  •     $TITLE=$_REQUEST['title'];
  • }
  • if(isset($_REQUEST['content']))
  • {
  •     $CONTENT=$_REQUEST['content'];
  • }
  • if(isset($_REQUEST['ssl'])){
  •     $SSL=$_REQUEST['ssl'];
  • }

  • if(isset($_REQUEST['port'])){
  •     $PORT=$_REQUEST['port'];
  • }

  • //echo "parse:
    "."$SMTP
    "."$FROM
    "."$USER
    "."$PASS
    "."$TO
    "."$TITLE
    "."$CONTENT
    "."$SSL
    "."$PORT
    \r\n";

  • //curl http://127.0.0.1/mail.php?smtp=smtp.xx.com&from=xxxx.com&user=xxxx.com&pass=xxxx&to=xxxx.com&title=test&content=test&ssl=YES
  • // /geo/app/scripts/sendmail.sh smtp.xx.com xxxx.com xxxx.com xxxx xxxx.com test test NO

  • $mail = new MySendMail();
  • if($SSL=="YES"){
  •     echo "SSL YES\r\n";
  •     //$CONTENT="$CONTENT:$PORT";
  •     $mail->setServer($SMTP, $FROM, $PASS,$PORT,true);
  • }else{
  •     echo "SSL NO\r\n";
  •     //$CONTENT="$CONTENT:25";
  •     $mail->setServer($SMTP, $FROM, $PASS);
  • }
  • $mail->setFrom($USER);
  • $mail->setReceiver($TO);
  • $mail->setMail($TITLE, "$CONTENT");
  • $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) {
  •         echo "port:"."$port
    \r\n"
    ;
  •         $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) {
  •         echo "from:"."$from
    \r\n"
    ;
  •         $this->_from = $from;
  •         return true;
  •     }

  •     /**

  •     * 设置收件人,多个收件人,调用多次.
  •     * @access public
  •     * @param string $to 收件人地址
  •     * @return boolean
  •     */
  •     public function setReceiver($to) {
  •         echo "to:"."$to
    \r\n"
    ;
  •         $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) {
  •         echo "$subject:"."$body

    \r\n\r\n"
    ;
  •         $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 sendmail\r\n", 250)
  •             );
  •         if(!empty($this->_userName)){
  •             $command[] = array("AUTH LOGIN\r\n", 334);
  •             $command[] = array($this->_userName . "\r\n", 334);
  •             $command[] = array($this->_password . "\r\n", 235);
  •         }

  •         //设置发件人
  •         $command[] = array("MAIL FROM: \r\n", 250);
  •         $header = "FROM: \r\n";

  •         //设置收件人
  •         if(!empty($this->_to)) {
  •             $count = count($this->_to);
  •             if($count == 1){
  •                 $command[] = array("RCPT TO: \r\n", 250);
  •                 $header .= "TO: \r\n";
  •             }
  •             else{
  •                 for($i=0; $i_to[$i] . ">\r\n", 250);
  •                     if($i == 0){
  •                         $header .= "TO: ";
  •                     }
  •                     elseif($i + 1 == $count){
  •                         $header .= ",\r\n";
  •                     }
  •                     else{
  •                         $header .= ",";
  •                     }
  •                 }
  •             }
  •         }

  •         //设置抄送
  •         if(!empty($this->_cc)) {
  •             $count = count($this->_cc);
  •             if($count == 1){
  •                 $command[] = array("RCPT TO: \r\n", 250);
  •                 $header .= "CC: \r\n";
  •             }
  •             else{
  •                 for($i=0; $i_cc[$i] . ">\r\n", 250);
  •                     if($i == 0){
  •                     $header .= "CC: ";
  •                     }
  •                     elseif($i + 1 == $count){
  •                         $header .= ",\r\n";
  •                     }
  •                     else{
  •                         $header .= ",";
  •                     }
  •                 }
  •             }
  •         }

  •         //设置秘密抄送
  •         if(!empty($this->_bcc)) {
  •             $count = count($this->_bcc);
  •             if($count == 1) {
  •                 $command[] = array("RCPT TO: \r\n", 250);
  •                 $header .= "BCC: \r\n";
  •             }
  •             else{
  •                 for($i=0; $i_bcc[$i] . ">\r\n", 250);
  •                     if($i == 0){
  •                     $header .= "BCC: ";
  •                     }
  •                     elseif($i + 1 == $count){
  •                         $header .= ",\r\n";
  •                     }
  •                     else{
  •                         $header .= ",";
  •                     }
  •                 }
  •             }
  •         }

  •         //主题
  •         $header .= "Subject: =?UTF-8?B?" . $this->_subject ."?=\r\n";
  •         if(isset($this->_attachment)) {
  •             //含有附件的邮件头需要声明成这个
  •             $header .= "Content-Type: multipart/mixed;\r\n";
  •         }
  •         elseif(false){
  •             //邮件体含有图片资源的,且包含的图片在邮件内部时声明成这个,如果是引用的远程图片,就不需要了
  •             $header .= "Content-Type: multipart/related;\r\n";
  •         }
  •         else{
  •             //html或者纯文本的邮件声明成这个
  •             $header .= "Content-Type: multipart/alternative;\r\n";
  •         }

  •         //邮件头分隔符
  •         $header .= "\t" . 'boundary="' . $separator . '"';

  •         $header .= "\r\nMIME-Version: 1.0\r\n";

  •         //这里开始是邮件的body部分,body部分分成几段发送
  •         $header .= "\r\n--" . $separator . "\r\n";
  •         $header .= "Content-Type:text/html; charset=utf-8\r\n";
  •         $header .= "Content-Transfer-Encoding: base64\r\n\r\n";
  •         $header .= $this->_body . "\r\n";
  •         $header .= "--" . $separator . "\r\n";

  •         //加入附件
  •         if(!empty($this->_attachment)){
  •             $count = count($this->_attachment);
  •             for($i=0; $igetMIMEType($this->_attachment[$i]) . '; name="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' . "\r\n";
  •                 $header .= "Content-Transfer-Encoding: base64\r\n";
  •                 $header .= 'Content-Disposition: attachment; filename="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' ."\r\n";
  •                 $header .= "\r\n";
  •                 $header .= $this->readFile($this->_attachment[$i]);
  •                 $header .= "\r\n--" . $separator . "\r\n";
  •             }
  •         }

  •         //结束邮件数据发送
  •         $header .= "\r\n.\r\n";


  •         $command[] = array("DATA\r\n", 354);
  •         $command[] = array($header, 250);
  •         $command[] = array("QUIT\r\n", 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 . '
    '
    ;
  •         //发送命令给服务器
  •         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 . '

    '
    ;

  •                 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, $code) {
  •         echo 'Send command:' . $command . ',expected code:' . $code . '
    '
    ;
  •         try {
  •             if(fwrite($this->_socket, $command)){
  •                 //当邮件内容分多次发送时,没有code,服务器没有返回
  •                 if(empty($code)) {
  •                     return true;
  •                 }
  •                 //读取服务器返回
  •                 $data = trim(fread($this->_socket, 1024));
  •                 echo 'response:' . $data . '

    '
    ;

  •                 if($data) {
  •                     $pattern = "/^".$code."+?/";
  •                     if(preg_match($pattern, $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); //SSL
  •         //stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); //TLS

  •         stream_set_blocking($this->_socket, 1); //设置阻塞模式
  •         $str = fread($this->_socket, 1024);
  •         if(!preg_match("/220+?/", $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;
  •     }
  • }






运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-155463-1-1.html 上篇帖子: 浅谈PHP代码设计结构 下篇帖子: PHP进制转换[实现2、8、16、36、64进制至10进制相互转换]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表