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 相关文章推荐
将RTF格式的文件转成HTML并在网页中显示的代码
Oct 09 PHP
vBulletin HACK----关于排版的两个HACK
Oct 09 PHP
php的list()的一步操作给一组变量进行赋值的使用
May 18 PHP
php错误提示failed to open stream: HTTP request failed!的完美解决方法
Jun 06 PHP
基于php常用正则表达式的整理汇总
Jun 08 PHP
php多层数组与对象的转换实例代码
Aug 05 PHP
thinkPHP删除前弹出确认框的简单实现方法
May 16 PHP
form自动提交实例讲解
Jul 10 PHP
PHP7下协程的实现方法详解
Dec 17 PHP
Laravel 5.4.36中session没有保存成功问题的解决
Feb 19 PHP
微信公众平台开发教程②微信端分享功能图文详解
Apr 10 PHP
YII框架实现自定义第三方扩展操作示例
Apr 26 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
咖啡豆要不要放冰箱的原因
2021/03/04 冲泡冲煮
PHP生成随机数的方法实例分析
2015/01/22 PHP
PHP验证终端类型是否为手机的简单实例
2017/02/07 PHP
php实现的统计字数函数定义与使用示例
2017/07/26 PHP
可以用来调试JavaScript错误的解决方案
2010/08/07 Javascript
Dom在ajax技术中的作用说明
2010/10/25 Javascript
一个可拖拽列宽表格实例演示
2012/11/26 Javascript
前端轻量级MVC框架CanJS详解
2014/09/26 Javascript
深入分析Javascript跨域问题
2015/04/17 Javascript
jQuery超简单选项卡完整实例
2015/09/26 Javascript
javascript 小数乘法结果错误的处理方法
2016/07/28 Javascript
js style.display=block显示布局错乱问题的解决方法
2016/09/21 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
2017/01/11 Javascript
js数字计算 误差问题的快速解决方法
2017/02/28 Javascript
浅谈regExp的test方法取得的值变化的原因及处理方法
2017/03/01 Javascript
jqueryUI tab标签页代码分享
2017/10/09 jQuery
详解webpack babel的配置
2018/01/09 Javascript
vue-cli脚手架引入图片的几种方法总结
2018/03/13 Javascript
学习JS中的DOM节点以及操作
2018/04/30 Javascript
微信小程序发布新版本时自动提示用户更新的方法
2019/06/07 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
将Django使用的数据库从MySQL迁移到PostgreSQL的教程
2015/04/11 Python
快速了解Python中的装饰器
2018/01/11 Python
python使用正则表达式来获取文件名的前缀方法
2018/10/21 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
pymongo insert_many 批量插入的实例
2020/12/05 Python
编辑个人求职信范文
2013/09/21 职场文书
大学总结自我鉴定
2014/01/18 职场文书
安全生产计划书
2014/05/04 职场文书
4s店活动策划方案
2014/08/25 职场文书
2014领导班子四风问题对照检查材料思想汇报
2014/09/21 职场文书
雨雪天气温馨提示
2015/07/15 职场文书
优秀共产党员事迹材料2016
2016/02/29 职场文书
德劲DE1108畅想
2021/04/22 无线电
python爬取新闻门户网站的示例
2021/04/25 Python
关于对TypeScript泛型参数的默认值理解
2022/07/15 Javascript