php基于socket实现SMTP发送邮件的方法


Posted in PHP onMarch 05, 2015

本文实例讲述了php基于socket实现SMTP发送邮件的方法。分享给大家供大家参考。具体分析如下:

php采用socket通过SMTP发送邮件。
用的是php的php-sockets扩展,可以发送纯文本和html格式的邮件。代码如下:

<?php

/**

* 邮件发送类

* 支持发送纯文本邮件和HTML格式的邮件

* @example

* $config = array(

*       "from" => "*****",

*       "to" => "***",

*       "subject" => "test",

*       "body" => "<b>test</b>",

*       "username" => "***",

*       "password" => "****",

*       "isHTML" => true

*   );

*

* $mail = new MySendMail();

*

* $mail->setServer("smtp.126.com");

*

* $mail->setMailInfo($config);

* if(!$mail->sendMail()) {

*   echo $mail->error();

*   return 1;

* }

*/

class MySendMail {

    /**

    * @var 邮件传输代理用户名

    * @access private

    */

    private $_userName;

    /**

    * @var 邮件传输代理密码

    * @access private

    */

    private $_password;

    /**

    * @var 邮件传输代理服务器地址

    * @access protected

    */

    protected $_sendServer;

    /**

    * @var 邮件传输代理服务器端口

    * @access protected

    */

    protected $_port=25;

    /**

    * @var 发件人

    * @access protected

    */

    protected $_from;

    /**

    * @var 收件人

    * @access protected

    */

    protected $_to;

    /**

    * @var 主题

    * @access protected

    */

    protected $_subject;

    /**

    * @var 邮件正文

    * @access protected

    */

    protected $_body;

    /**

    * @var 是否是HTML格式的邮件

    * @access protected

    */

    protected $_isHTML=false;

    /**

    * @var socket资源

    * @access protected

    */

    protected $_socket;

    /**

    * @var 错误信息

    * @access protected

    */

    protected $_errorMessage;

    public function __construct($from="", $to="", $subject="", $body="", $server="", $username="", $password="",$isHTML="", $port="") {

        if(!empty($from)){

            $this->_from = $from;

        }

        if(!empty($to)){

            $this->_to = $to;

        }

        if(!empty($subject)){

            $this->_subject = $subject;

        }

        if(!empty($body)){

            $this->_body = $body;

        }

        if(!empty($isHTML)){

            $this->_isHTML = $isHTML;

        }

        if(!empty($server)){

            $this->_sendServer = $server;

        }

        if(!empty($port)){

            $this->_port = $port;

        }

        if(!empty($username)){

            $this->_userName = $username;

        }

        if(!empty($password)){

            $this->_password = $password;

        }

    }

    /**

    * 设置邮件传输代理

    * @param string $server 代理服务器的ip或者域名

    * @param int $port 代理服务器的端口,smtp默认25号端口

    * @param int $localPort 本地端口

    * @return boolean

    */

    public function setServer($server, $port=25) {

        if(!isset($server) || empty($server) || !is_string($server)) {

            $this->_errorMessage = "first one is an invalid parameter";

            return false;

        }

        if(!is_numeric($port)){

            $this->_errorMessage = "first two is an invalid parameter";

            return false;

        }

        $this->_sendServer = $server;

        $this->_port = $port;

        return true;

    }

    /**

    * 设置邮件

    * @access public

    * @param array $config 邮件配置信息

    * 包含邮件发送人、接收人、主题、内容、邮件传输代理的验证信息

    * @return boolean

    */

    public function setMailInfo($config) {

        if(!is_array($config) || count($config) < 6){

            $this->_errorMessage = "parameters are required";

            return false;

        }

        $this->_from = $config['from'];

        $this->_to = $config['to'];

        $this->_subject = $config['subject'];

        $this->_body = $config['body'];

        $this->_userName = $config['username'];

        $this->_password = $config['password'];

        if(isset($config['isHTML'])){

            $this->_isHTML = $config['isHTML'];

        }

        return true;

    }

    /**

    * 发送邮件

    * @access public

    * @return boolean

    */

    public function sendMail() {

        $command = $this->getCommand();

        $this->socket();

        foreach ($command as $value) {

            if($this->sendCommand($value[0], $value[1])) {

                continue;

            }

            else{

                return false;

            }

        }

        $this->close(); //其实这里也没必要关闭,smtp命令:QUIT发出之后,服务器就关闭了连接,本地的socket资源会自动释放

        echo 'Mail OK!';

        return true;

    }

    /**

    * 返回错误信息

    * @return string

    */

    public function error(){

        if(!isset($this->_errorMessage)) {

            $this->_errorMessage = "";

        }

        return $this->_errorMessage;

    }

    /**

    * 返回mail命令

    * @access protected

    * @return array

    */

    protected function getCommand() {

        if($this->_isHTML) {

            $mail = "MIME-Version:1.0\r\n";

            $mail .= "Content-type:text/html;charset=utf-8\r\n";

            $mail .= "FROM:test<" . $this->_from . ">\r\n";

            $mail .= "TO:<" . $this->_to . ">\r\n";

            $mail .= "Subject:" . $this->_subject ."\r\n\r\n";

            $mail .= $this->_body . "\r\n.\r\n";

        }

        else{

            $mail = "FROM:test<" . $this->_from . ">\r\n";

            $mail .= "TO:<" . $this->_to . ">\r\n";

            $mail .= "Subject:" . $this->_subject ."\r\n\r\n";

            $mail .= $this->_body . "\r\n.\r\n";

        }

        $command = array(

                array("HELO sendmail\r\n", 250),

                array("AUTH LOGIN\r\n", 334),

                array(base64_encode($this->_userName) . "\r\n", 334),

                array(base64_encode($this->_password) . "\r\n", 235),

                array("MAIL FROM:<" . $this->_from . ">\r\n", 250),

                array("RCPT TO:<" . $this->_to . ">\r\n", 250),

                array("DATA\r\n", 354),

                array($mail, 250),

                array("QUIT\r\n", 221)

        );

        return $command;

    }

    /**

    * @access protected

    * @param string $command 发送到服务器的smtp命令

    * @param int $code 期望服务器返回的响应吗

    * @param boolean

    */

    protected function sendCommand($command, $code) {

        echo 'Send command:' . $command . ',expected code:' . $code . '<br />';

        //发送命令给服务器

        try{

            if(socket_write($this->_socket, $command, strlen($command))){

                //读取服务器返回

                $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 private

    * @return boolean

    */

    private function socket() {

        if(!function_exists("socket_create")) {

            $this->_errorMessage = "extension php-sockets must be enabled";

            return false;

        }

        //创建socket资源

        $this->_socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));

        if(!$this->_socket) {

            $this->_errorMessage = socket_strerror(socket_last_error());

            return false;

        }

        //连接服务器

        if(!socket_connect($this->_socket, $this->_sendServer, $this->_port)) {

            $this->_errorMessage = socket_strerror(socket_last_error());

            return false;

        }

        socket_read($this->_socket, 1024);

        return true;

    }

    /**

    * 关闭socket

    * @access private

    * @return boolean

    */

    private 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;

    }

}

/**************************** Test ***********************************/

$config = array(

        "from" => "XXXXX",

        "to" => "XXXXX",

        "subject" => "test",

        "body" => "<b>test</b>",

        "username" => "XXXXX",

        "password" => "******",

        //"isHTML" => true

    );

$mail = new MySendMail();

$mail->setServer("smtp.126.com");

$mail->setMailInfo($config);

if(!$mail->sendMail()) {

    echo $mail->error();

    return 1;

}

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
WINDOWS 2000下使用ISAPI方式安装PHP
Sep 05 PHP
在PHP中利用XML技术构造远程服务(下)
Oct 09 PHP
Phpbean路由转发的php代码
Jan 10 PHP
PHP stristr() 函数(不区分大小写的字符串查找)
Jun 03 PHP
IIS+fastcgi下PHP运行超时问题的解决办法详解
Jun 20 PHP
php中解析带中文字符的url函数分享
Jan 20 PHP
PHP实现的带超时功能get_headers函数
Feb 10 PHP
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
Oct 20 PHP
smarty中改进truncate使其支持中文的方法
May 30 PHP
Symfony2创建基于域名的路由相关示例
Nov 14 PHP
php实现socket推送技术的示例
Dec 20 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
Feb 28 PHP
php计算两个整数的最大公约数常用算法小结
Mar 05 #PHP
PHP 使用memcached简单示例分享
Mar 05 #PHP
Ubuntu中搭建Nginx、PHP环境最简单的方法
Mar 05 #PHP
PHP实现支持SSL连接的SMTP邮件发送类
Mar 05 #PHP
PHP 使用redis简单示例分享
Mar 05 #PHP
memcache一致性hash的php实现方法
Mar 05 #PHP
PHP将session信息存储到数据库的类实例
Mar 04 #PHP
You might like
PHP 引用文件技巧
2010/03/02 PHP
[原创]PHP正则删除html代码中a标签并保留标签内容的方法
2017/05/23 PHP
PHP生成(支持多模板)二维码海报代码
2018/04/30 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
图像替换新技术 状态域方法
2010/01/28 Javascript
JS判断对象是否存在的10种方法总结
2013/12/23 Javascript
javascript实例--教你实现扑克牌洗牌功能
2014/05/15 Javascript
JavaScript实现对下拉列表值进行排序的方法
2015/07/15 Javascript
jQuery多文件异步上传带进度条实例代码
2016/08/16 Javascript
js获取腾讯视频ID的方法
2016/10/03 Javascript
详解js的延迟对象、跨域、模板引擎、弹出层、AJAX【附实例下载】
2016/12/19 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
微信小程序 参数传递实例代码
2017/03/20 Javascript
原生JS实现九宫格抽奖效果
2017/04/01 Javascript
layui2.0使用table+laypage实现真分页
2019/07/27 Javascript
vue 解决文本框被键盘遮住的问题
2019/11/06 Javascript
vue el-table实现自定义表头
2019/12/11 Javascript
Node.js API详解之 dns模块用法实例分析
2020/05/15 Javascript
详解微信小程序动画Animation执行过程
2020/09/23 Javascript
微信小程序用户登录和登录态维护的实现
2020/12/10 Javascript
python下MySQLdb用法实例分析
2015/06/08 Python
Python的for和break循环结构中使用else语句的技巧
2016/05/24 Python
Python实现导出数据生成excel报表的方法示例
2017/07/12 Python
Python基于回溯法子集树模板实现图的遍历功能示例
2017/09/05 Python
Python中实例化class的执行顺序示例详解
2018/10/14 Python
安装完Python包然后找不到模块的解决步骤
2020/02/13 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
使用keras实现Precise, Recall, F1-socre方式
2020/06/15 Python
纯CSS3实现表单验证效果(非常不错)
2017/01/18 HTML / CSS
Nike香港官网:Nike HK
2019/03/23 全球购物
表彰大会主持词
2014/03/26 职场文书
先进集体申报材料
2014/12/25 职场文书
实验心得体会范文
2016/01/25 职场文书
浅谈自定义校验注解ConstraintValidator
2021/06/30 Java/Android
在Python 中将类对象序列化为JSON
2022/04/06 Python