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初学者们头痛的十四个问题
Jan 15 PHP
PHP开发规范手册之PHP代码规范详解
Jan 13 PHP
探讨php中header的用法详解
Jun 07 PHP
如何取得中文字符串中出现次数最多的子串
Aug 08 PHP
php二维数组排序方法(array_multisort usort)
Dec 25 PHP
php查询mysql数据库并将结果保存到数组的方法
Mar 18 PHP
Laravel 5框架学习之Laravel入门和新建项目
Apr 07 PHP
Yii扩展组件编写方法实例分析
Jun 29 PHP
php获取汉字拼音首字母的方法
Oct 21 PHP
使用php从身份证号中获取一系列线索(星座、生肖、生日等)
May 11 PHP
thinkphp框架实现数据添加和显示功能
Jun 29 PHP
微信公众号实现会员卡领取功能
Jun 08 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新手上路(十一)
2006/10/09 PHP
php查看session内容的函数
2008/08/27 PHP
网页游戏开发入门教程二(游戏模式+系统)
2009/11/02 PHP
删除无限分类并同时删除它下面的所有子分类的方法
2010/08/08 PHP
PHP清除缓存的几种方法总结
2017/09/12 PHP
PHP数据源架构模式之表入口模式实例分析
2020/01/23 PHP
jquery ajax提交表单数据的两种方式
2009/11/24 Javascript
关于js日期转化为毫秒数“节省20%的效率和和节省9个字符“问题
2012/03/01 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
2013/04/02 Javascript
基于jQuery实现网页打印功能
2015/12/01 Javascript
JavaScript数据类型学习笔记
2016/01/25 Javascript
jQuery验证表单格式的使用方法
2017/01/10 Javascript
JavaScript事件方法(实例讲解)
2017/06/27 Javascript
jQuery实现浏览器之间跳转并传递参数功能【支持中文字符】
2018/03/28 jQuery
微信开发之微信jssdk录音功能开发示例
2018/10/22 Javascript
Puppeteer 爬取动态生成的网页实战
2018/11/14 Javascript
jquery 验证用户名是否重复代码实例
2019/05/14 jQuery
JavaScript实现图片的放大缩小及拖拽功能示例
2019/05/14 Javascript
Vue中el-form标签中的自定义el-select下拉框标签功能
2020/04/20 Javascript
python计数排序和基数排序算法实例
2014/04/25 Python
Python for Informatics 第11章之正则表达式(四)
2016/04/21 Python
python整小时 整天时间戳获取算法示例
2019/02/20 Python
python从list列表中选出一个数和其对应的坐标方法
2019/07/20 Python
Perry Ellis官网:美国男士品味服装
2016/12/09 全球购物
华为消费者德国官方网站:HUAWEI德国
2020/11/03 全球购物
社区包粽子活动方案
2014/01/21 职场文书
珍珠鸟教学反思
2014/02/01 职场文书
公证委托书大全
2014/04/04 职场文书
2014年党支部学习材料
2014/05/19 职场文书
在职员工证明书
2014/09/19 职场文书
项目技术负责人岗位职责
2015/04/13 职场文书
办公室年度工作总结2015
2015/05/21 职场文书
领导欢送会主持词
2015/07/06 职场文书
莫言获奖感言(全文)
2015/07/31 职场文书
Python中基础数据类型 set集合知识点总结
2021/08/02 Python
微软团队与 NASA 科学家和惠普企业(HPE)的工程师合作
2022/04/21 数码科技