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 相关文章推荐
配置Apache2.2+PHP5+CakePHP1.2+MySQL5运行环境
Apr 25 PHP
在PHP中使用X-SendFile头让文件下载更快
Jun 01 PHP
PHP动态编译出现Cannot find autoconf的解决方法
Nov 05 PHP
PHP中的闭包(匿名函数)浅析
Feb 07 PHP
php筛选不存在的图片资源
Apr 28 PHP
PHP中预定义的6种接口介绍
May 12 PHP
详解PHP对象的串行化与反串行化
Jan 24 PHP
php项目开发中用到的快速排序算法分析
Jun 25 PHP
PHP编程实现csv文件导入mysql数据库的方法
Apr 29 PHP
关于PHP中协程和阻塞的一些理解与思考
Aug 11 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
Aug 11 PHP
Yii2.0框架behaviors方法使用实例分析
Sep 30 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循环跳出的问题
2013/07/01 PHP
PHP对接微信公众平台消息接口开发流程教程
2014/03/25 PHP
PHP测试框架PHPUnit组织测试操作示例
2018/05/28 PHP
TimergliderJS 一个基于jQuery的时间轴插件
2011/12/07 Javascript
jquery 插件学习(四)
2012/08/06 Javascript
JQuery解析HTML、JSON和XML实例详解
2014/03/29 Javascript
javascript常用函数归纳整理
2014/10/31 Javascript
JS动态显示表格上下frame的方法
2015/03/31 Javascript
JS组件Bootstrap导航条使用方法详解
2016/04/29 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
Node.js使用gm拼装sprite图片
2017/07/04 Javascript
微信小程序按钮去除边框线分享页面功能
2018/08/27 Javascript
javascript防抖函数debounce详解
2019/06/11 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
使用js实现一个简单的滚动条过程解析
2019/09/10 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
简单了解JavaScript arguement原理及作用
2020/05/28 Javascript
Vue 实例中使用$refs的注意事项
2021/01/29 Vue.js
利用Python生成文件md5校验值函数的方法
2017/01/10 Python
Python编程实现蚁群算法详解
2017/11/13 Python
解决使用pycharm提交代码时冲突之后文件丢失找回的方法
2018/08/05 Python
Python使用matplotlib绘制随机漫步图
2018/08/27 Python
python清除字符串前后空格函数的方法
2018/10/21 Python
详解重置Django migration的常见方式
2019/02/15 Python
python制作填词游戏步骤详解
2019/05/05 Python
Django处理多用户类型的方法介绍
2019/05/18 Python
对Django url的几种使用方式详解
2019/08/06 Python
Django 自动生成api接口文档教程
2019/11/19 Python
python cv2截取不规则区域图片实例
2019/12/21 Python
Python定时任务框架APScheduler原理及常用代码
2020/10/05 Python
Lookfantastic希腊官网:英国知名美妆购物网站
2018/09/15 全球购物
交警个人先进事迹材料
2014/05/11 职场文书
2015年美容师个人工作总结
2015/10/14 职场文书
详解Node.js如何处理ES6模块
2021/05/15 Javascript
Python开发工具Pycharm的安装以及使用步骤总结
2021/06/24 Python