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 相关文章推荐
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
Sep 09 PHP
php 连接mssql数据库 初学php笔记
Mar 01 PHP
PHP 一个页面执行时间类代码
Mar 05 PHP
php中长文章分页显示实现代码
Sep 29 PHP
php设置编码格式的方法
Mar 05 PHP
兼容ie6浏览器的php下载文件代码分享
Jul 14 PHP
PHP 5.3新增魔术方法__invoke概述
Jul 23 PHP
php将access数据库转换到mysql数据库的方法
Dec 24 PHP
PHP实现文件上传和多文件上传
Dec 24 PHP
PHP编程计算文件或数组中单词出现频率的方法
May 22 PHP
PHP里的$_GET数组介绍
Mar 22 PHP
PHP数组实际占用内存大小原理解析
Dec 11 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校验ISBN码的函数代码
2011/01/17 PHP
PHP如何利用P3P实现跨域
2013/08/24 PHP
Zend Framework框架之Zend_Mail实现发送Email邮件验证功能及解决标题乱码的方法
2016/03/21 PHP
PHP结合Redis+MySQL实现冷热数据交换应用案例详解
2019/07/09 PHP
ArrayList类(增强版)
2007/04/04 Javascript
关于flash遮盖div浮动层的解决方法
2010/07/17 Javascript
js继承的实现代码
2010/08/05 Javascript
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
ExtJS 刷新后如何默认选中刷新前最后一次选中的节点
2014/04/03 Javascript
jQuery学习笔记之总体架构
2014/06/03 Javascript
nodejs调用cmd命令实现复制目录
2015/05/04 NodeJs
JS实现的Select三级下拉菜单代码
2015/08/20 Javascript
input 禁止输入特殊字符的四种实现方式
2016/08/24 Javascript
Vue Spa切换页面时更改标题的实例代码
2017/07/15 Javascript
jQuery实现的简单前端搜索功能示例
2017/10/28 jQuery
Angular使用过滤器uppercase/lowercase实现字母大小写转换功能示例
2018/03/27 Javascript
jQuery实现的滑块滑动导航效果示例
2018/06/04 jQuery
vue生命周期实例小结
2018/08/15 Javascript
对于防止按钮重复点击的尝试详解
2019/04/22 Javascript
vue使用map代替Aarry数组循环遍历的方法
2020/04/30 Javascript
python实现每次处理一个字符的三种方法
2014/10/09 Python
Python利用多进程将大量数据放入有限内存的教程
2015/04/01 Python
vscode 远程调试python的方法
2017/12/01 Python
解决Python pandas plot输出图形中显示中文乱码问题
2018/12/12 Python
Python操作配置文件ini的三种方法讲解
2019/02/22 Python
python利用itertools生成密码字典并多线程撞库破解rar密码
2019/08/12 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
html+js 实现markdown编辑器效果
2019/10/23 HTML / CSS
世界最大的私人旅行指南出版商:孤独星球
2016/08/23 全球购物
实习护理工作自我评价
2013/09/25 职场文书
《乌塔》教学反思
2014/02/17 职场文书
感恩教师节演讲稿
2014/09/03 职场文书
绿色校园广播稿
2014/10/13 职场文书
2014年法院工作总结
2014/11/24 职场文书
大学四年个人总结
2015/03/03 职场文书
2015年高校辅导员工作总结
2015/04/20 职场文书