php下使用SMTP发邮件的代码


Posted in PHP onJanuary 10, 2008

最近一个项目需要用到SMTP发送邮件,之前的库类不存在了,又不喜欢安装pear或者使用pear的net/smtp类,感觉太复杂了。就直接从discuz中抽取出核心稍微修改了下。
   从协议分析网上,查找到SMTP协议的命令和应答,SMTP协议在发送SMTP和接收SMTP之间的会话是靠发送SMTP的SMTP命令和接收SMTP反馈的应答来完成的。常用的命令如下:
   HELLO<domain><CRLF>识别发送方到接收SMTP的一个HELLO命令
   MAIL FROM:<reverse-path><CRLF><reverse-path>为发送者地址。此命令告诉接收方一个新邮件发送的开始,并对所有的状态和缓冲区进行初始化。此命令开始一个邮件传输处理,最终完成将邮件数据传送到一个或多个邮箱中。
   RCPT TO:<forward-path><CRLF><forward-path>标识各个邮件接收者的地址  
   DATA<CRLF>
       接收SMTP将把其后的行为看作邮件数据去处理,以<CRLF>.<CRLF>标识数据的结尾。
   REST<CRLF>退出/复位当前的邮件传输
   NOOP<CRLF>要求接收SMTP仅做OK应答。(用于测试)
   QUIT<CRLF>要求接收SMTP返回一个OK应答并关闭传输。
   VRFY<string><CRLF>验证指定的邮箱是否存在,由于安全因素,服务器多禁止此命令。
   EXPN<string><CRLF>验证给定的邮箱列表是否存在,扩充邮箱列表,也常禁止使用。
   HELP<CRLF>查询服务器支持什么命令

   注:<CRLF>为回车、换行,ASCII码分别为13、10(十进制)。

   另外,可以在command下,使用telnet来进行简单的手工使用SMTP。
  比如:

telnet smtp.263.net 25 
Trying 211.150.96.25... 
Connected to smtp.263.net. 
Escape character is '^]'. 
220 Welcome to coremail System(With Anti-Spam) 2.1 for 263(040326) 
HELO weiqiong@cctk.net 
250 smtp.263.net 
mail from:weiqiong@cctk.net 
250 Ok 
rcpt to:g2_t1@263.net 
250 Ok 
data 
354 End data with <CR><LF>.<CR><LF> 
haha 

250 Ok: queued as B9E452FF3E 
quit 
221 Bye 
Connection closed by foreign host. 

   在此基础上就可以写出一个简单的SMTP类了。

<? 
class stmp{ 

    private $mailcfg=array(); 
    private $error_msg=''; 

    function __construct($mailcfg){ 

        $this->mailcfg=$mailcfg; 

    } 

    public function send($mail){ 
        $mailcfg=$this->mailcfg; 
        if(!$fp = fsockopen($mailcfg['server'], $mailcfg['port'], $errno, $errstr, 30)) { 
            return $this->error("($mailcfg[server]:$mailcfg[port]) CONNECT - Unable to connect to the SMTP server, please check your \"mail_config.php\"."); 
        } 
         stream_set_blocking($fp, true); 
         $lastmessage = fgets($fp, 512); 
        if(substr($lastmessage, 0, 3) != '220') { 
            return $this->error("$mailcfg[server]:$mailcfg[port] CONNECT - $lastmessage"); 
        } 
        fputs($fp, ($mailcfg['auth'] ? 'EHLO' : 'HELO')." ".$mailcfg['auth_username']."\r\n"); 
        $lastmessage = fgets($fp, 512); 
        if(substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250) { 
            return $this->error("($mailcfg[server]:$mailcfg[port]) HELO/EHLO - $lastmessage"); 
        } 
        while(1) { 
            if(substr($lastmessage, 3, 1) != '-' || empty($lastmessage)) { 
                 break; 
             } 
             $lastmessage = fgets($fp, 512); 
        } 
        if($mailcfg['auth']) { 
            fputs($fp, "AUTH LOGIN\r\n"); 
            $lastmessage = fgets($fp, 512); 
            if(substr($lastmessage, 0, 3) != 334) { 
                return $this->error("($mailcfg[server]:$mailcfg[port]) AUTH LOGIN - $lastmessage"); 
            } 
            fputs($fp, base64_encode($mailcfg['auth_username'])."\r\n"); 
            $lastmessage = fgets($fp, 512); 
            if(substr($lastmessage, 0, 3) != 334) { 
                return $this->error("($mailcfg[server]:$mailcfg[port]) USERNAME - $lastmessage"); 
            } 

            fputs($fp, base64_encode($mailcfg['auth_password'])."\r\n"); 
            $lastmessage = fgets($fp, 512); 
            if(substr($lastmessage, 0, 3) != 235) { 
                return $this->error("($mailcfg[server]:$mailcfg[port]) PASSWORD - $lastmessage"); 
            } 

            $email_from = $mailcfg['from']; 
        } 
        fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n"); 
        $lastmessage = fgets($fp, 512); 
        if(substr($lastmessage, 0, 3) != 250) { 
            fputs($fp, "MAIL FROM: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n"); 
            $lastmessage = fgets($fp, 512); 
            if(substr($lastmessage, 0, 3) != 250) { 
                return $this->error("($mailcfg[server]:$mailcfg[port]) MAIL FROM - $lastmessage"); 
            } 
        } 

        $email_to=$mail['to']; 
        foreach(explode(',', $email_to) as $touser) { 
            $touser = trim($touser); 
            if($touser) { 
                fputs($fp, "RCPT TO: <$touser>\r\n"); 
                $lastmessage = fgets($fp, 512); 
                if(substr($lastmessage, 0, 3) != 250) { 
                    fputs($fp, "RCPT TO: <$touser>\r\n"); 
                    $lastmessage = fgets($fp, 512); 
                    return $this->error("($mailcfg[server]:$mailcfg[port]) RCPT TO - $lastmessage"); 
                } 
            } 
        } 
        fputs($fp, "DATA\r\n"); 
        $lastmessage = fgets($fp, 512); 
        if(substr($lastmessage, 0, 3) != 354) { 
            return $this->error("($mailcfg[server]:$mailcfg[port]) DATA - $lastmessage"); 
        } 
        $str="To: $email_to\r\nFrom: $email_from\r\nSubject: ".$mail['subject']."\r\n\r\n".$mail['content']."\r\n.\r\n"; 
        fputs($fp, $str); 
        fputs($fp, "QUIT\r\n"); 
        return true; 
    } 

    public function get_error(){ 
        return $this->error_msg; 
    } 

    private function error($msg){ 
        $this->error_msg.=$msg; 
        return false; 
    } 


?> 

    简单的调用例子:

<? 
$mailcfg['server'] = 'smtp.163.com'; 

        $mailcfg['port'] = '25'; 

        $mailcfg['auth'] = 1; 
        $mailcfg['from'] = 'test <test@163.com>'; 

        $mailcfg['auth_username'] = 'test'; 

        $mailcfg['auth_password'] = 'password';     
        $stmp=new stmp($mailcfg); 
        $mail=array('to'=>'test@gmail.com','subject'=>'测试标题','content'=>'邮件内容<a href="http://www.phpobject.net">PHP面向对象</a>'); 
        if(!$stmp->send($mail)){ 
            echo $stmp->get_error(); 
        }else{ 
            echo 'mail succ!'; 
        } 
?> 

  如果发送成功,你就可以去邮箱查看邮件了。^_^

PHP 相关文章推荐
强烈推荐:php.ini中文版(1)
Oct 09 PHP
木翼下载系统中说明的PHP安全配置方法
Jun 16 PHP
PhpMyAdmin中无法导入sql文件的解决办法
Jan 08 PHP
php下关于中英数字混排的字符串分割问题
Apr 06 PHP
PHP面向对象之旅:深入理解static变量与方法
Jan 06 PHP
PHP函数http_build_query使用详解
Aug 20 PHP
ThinkPHP查询返回简单字段数组的方法
Aug 25 PHP
PHP中魔术变量__METHOD__与__FUNCTION__的区别
Sep 29 PHP
详解PHP中instanceof关键字及instanceof关键字有什么作用
Nov 05 PHP
PHP文件缓存smarty模板应用实例分析
Feb 26 PHP
thinkPHP自定义类实现方法详解
Nov 30 PHP
PHP生成随机数的方法总结
Mar 01 PHP
ZF等常用php框架中存在的问题
Jan 10 #PHP
逐步提升php框架的性能
Jan 10 #PHP
在PHP中使用Sockets 从Usenet中获取文件
Jan 10 #PHP
php扩展ZF――Validate扩展
Jan 10 #PHP
set_include_path在win和linux下的区别
Jan 10 #PHP
php模板之Phpbean的目录结构
Jan 10 #PHP
Phpbean路由转发的php代码
Jan 10 #PHP
You might like
[原创]php集成安装包wampserver修改密码后phpmyadmin无法登陆的解决方法
2016/11/23 PHP
Laravel框架中集成MongoDB和使用详解
2019/10/17 PHP
jquery给图片添加鼠标经过时的边框效果
2013/11/12 Javascript
javascript计算当月剩余天数(天数计算器)示例代码
2014/01/09 Javascript
jquery删除指定的html标签并保留标签内文本内容的方法
2014/04/02 Javascript
JQuery 使用attr方法实现下拉列表选中
2014/10/13 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
javascript中使用new与不使用实例化对象的区别
2015/06/22 Javascript
浅谈jQuery的offset()方法及示例分享
2015/07/17 Javascript
jquery实现的V字形显示效果代码
2015/10/27 Javascript
Node.js中Request模块处理HTTP协议请求的基本使用教程
2016/03/31 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
input获取焦点时底部菜单被顶上来问题的解决办法
2017/01/24 Javascript
React 路由懒加载的几种实现方案
2018/10/23 Javascript
Vue表单绑定的实例代码(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)
2019/05/13 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
2020/03/03 Javascript
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
解决ant Design中Select设置initialValue时的大坑
2020/10/29 Javascript
[01:00] DOTA2英雄背景故事第五期之重力引力法则谜团
2020/07/16 DOTA
Python回调函数用法实例详解
2015/07/02 Python
Python实现大文件排序的方法
2015/07/10 Python
简单讲解Python中的数字类型及基本的数学计算
2016/03/11 Python
详解常用查找数据结构及算法(Python实现)
2016/12/09 Python
python爬虫框架scrapy实战之爬取京东商城进阶篇
2017/04/24 Python
python取余运算符知识点详解
2019/06/27 Python
django drf框架自带的路由及最简化的视图
2019/09/10 Python
利用css3画个同心圆示例代码
2017/07/03 HTML / CSS
英国设计师珠宝网站:Joshua James Jewellery
2020/03/01 全球购物
医学专业应届生的自我评价
2014/02/28 职场文书
汽车运用工程专业求职信
2014/06/18 职场文书
美术专业自荐信
2014/07/07 职场文书
单位委托书格式范本
2014/09/29 职场文书
财务人员岗位职责
2015/02/03 职场文书
防卫过当辩护词
2015/05/21 职场文书
MySQL 外连接语法之 OUTER JOIN
2022/04/09 MySQL
使用refresh_token实现无感刷新页面
2022/04/26 Javascript