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+DBM的同学录程序(4)
Oct 09 PHP
php上传、管理照片示例
Oct 09 PHP
PHP 根据IP地址控制访问的代码
Apr 22 PHP
php计算程序运行时间的简单例子分享
May 10 PHP
ThinkPHP模板自定义标签使用方法
Jun 26 PHP
Codeigniter的一些优秀特性总结
Jan 21 PHP
PHP使用strtotime计算两个给定日期之间天数的方法
Mar 18 PHP
PHP入门教程之数组用法汇总(创建,删除,遍历,排序等)
Sep 11 PHP
php简单截取字符串代码示例
Oct 19 PHP
php 删除指定文件夹的实例讲解
Jul 25 PHP
Thinkphp5行为使用方法汇总
Dec 21 PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
Aug 21 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
PHP4之真OO
2006/10/09 PHP
destoon各类调用汇总
2014/06/20 PHP
PHP实现在线阅读PDF文件的方法
2015/06/17 PHP
php实现的数字验证码及数字运算验证码
2015/07/30 PHP
PHP制作用户注册系统
2015/10/23 PHP
Jquery实现Div上下移动示例
2014/04/23 Javascript
jQuery中attr()方法用法实例
2015/01/05 Javascript
基于javascript、ajax、memcache和PHP实现的简易在线聊天室
2015/02/03 Javascript
浅谈JavaScript中setInterval和setTimeout的使用问题
2015/08/01 Javascript
2016年最热门的15 款代码语法高亮工具,美化你的代码
2016/01/06 Javascript
Easyui Tree获取当前选择节点的所有顶级父节点
2017/02/14 Javascript
原生js实现瀑布流布局
2017/03/08 Javascript
ES6正则表达式的一些新功能总结
2017/05/09 Javascript
React学习笔记之条件渲染(一)
2017/07/02 Javascript
JavaScript实现的简单加密解密操作示例
2018/06/01 Javascript
AngularJS发送异步Get/Post请求方法
2018/08/13 Javascript
详解Webpack-dev-server的proxy用法
2018/09/08 Javascript
Vue2.x通用条件搜索组件的封装及应用详解
2019/05/28 Javascript
python实现用户登录系统
2016/05/21 Python
Python 中Pickle库的使用详解
2018/02/24 Python
keras模型保存为tensorflow的二进制模型方式
2020/05/25 Python
Python如何安装第三方模块
2020/05/28 Python
HTML5 新旧语法标记对我们有什么好处
2012/12/13 HTML / CSS
重新定义牛仔布,100美元以下:Warp + Weft
2018/07/25 全球购物
德国前卫设计师时装在线商店:Luxury Loft
2019/11/04 全球购物
Chinti & Parker官网:奢华羊绒女装和创新针织设计
2021/01/01 全球购物
伦敦鲜花递送:Flower Station
2021/02/03 全球购物
本科毕业生求职自荐信
2014/02/03 职场文书
高一新生军训感言
2014/03/02 职场文书
信息技术培训感言
2014/03/06 职场文书
农业局学习党的群众路线教育实践活动心得体会
2014/03/07 职场文书
采购求职信
2014/03/17 职场文书
担保书格式
2015/01/20 职场文书
董事长助理岗位职责
2015/02/11 职场文书
2015年专项整治工作总结
2015/04/03 职场文书
SpringAop日志找不到方法的处理
2021/06/21 Java/Android