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 相关文章推荐
建立文件交换功能的脚本(一)
Oct 09 PHP
PHP 手机归属地查询 api
Feb 08 PHP
php函数之子字符串替换&amp;#65279; str_replace
Mar 23 PHP
php基础教程 php内置函数实例教程
Aug 21 PHP
CodeIgniter框架过滤HTML危险代码
Jun 12 PHP
PHP发送短信代码分享
Aug 11 PHP
浅谈PHP中foreach/in_array的使用
Nov 02 PHP
php上传图片并压缩的实现方法
Dec 22 PHP
PHP小偷程序的设计与实现方法详解
Oct 15 PHP
ZendFramework框架实现连接两个或多个数据库的方法
Dec 08 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
Aug 21 PHP
Yii 使用intervention/image拓展实现图像处理功能
Jun 22 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&amp;java(一)
2006/10/09 PHP
Wordpress 相册插件 NextGEN-Gallery 添加目录将中文转为拼音的解决办法
2010/12/29 PHP
PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
2011/07/01 PHP
PHP daddslashes 使用方法介绍
2012/10/26 PHP
PHP计数器的实现代码
2013/06/08 PHP
PHP CURL与java http使用方法详解
2018/01/26 PHP
Javascript 静态页面实现随机显示广告的办法
2010/11/17 Javascript
有趣的JavaScript数组长度问题代码说明
2011/01/20 Javascript
jQuery 操作option的实现代码
2011/03/03 Javascript
别了 JavaScript中的isXX系列
2012/08/01 Javascript
javascript操作css属性
2013/12/30 Javascript
浅谈JavaScript function函数种类
2014/12/29 Javascript
详解JavaScript中void语句的使用
2015/06/04 Javascript
javascript实现控制的多级下拉菜单
2015/07/05 Javascript
基于jQuery全屏焦点图左右切换插件responsiveslides
2015/09/07 Javascript
javascript之Array 数组对象详解
2016/06/07 Javascript
canvas绘制多边形
2017/02/24 Javascript
Express使用html模板的详细代码
2017/09/18 Javascript
vue2中的keep-alive使用总结及注意事项
2017/12/21 Javascript
JavaScript基础心法 数据类型
2018/03/05 Javascript
微信小程序实现滴滴导航tab切换效果
2018/07/24 Javascript
Node.js JSON模块用法实例分析
2019/01/04 Javascript
JS栈stack类的实现与使用方法示例
2019/01/31 Javascript
解决vue项目中页面调用数据 在数据加载完毕之前出现undefined问题
2019/11/14 Javascript
[03:00]2014DOTA2国际邀请赛 Titan淘汰潸然泪下Ohaiyo专访
2014/07/15 DOTA
使用Python刷淘宝喵币(低阶入门版)
2019/10/30 Python
Python通过socketserver处理多个链接
2020/03/18 Python
python爬虫泛滥的解决方法详解
2020/11/25 Python
CSS3中Transition动画属性用法详解
2016/07/04 HTML / CSS
MediaMarkt比利时:欧洲最大电器连锁店
2020/12/21 全球购物
小学教师节活动方案
2014/01/31 职场文书
洗车工岗位职责
2014/03/15 职场文书
党员公开承诺书范文
2014/03/25 职场文书
学习党史心得体会2016
2016/01/23 职场文书
2016年安全生产先进个人事迹材料
2016/02/29 职场文书
基于CSS制作创意端午节专属加载特效
2022/06/01 HTML / CSS