依扬博客 Blog For Business and IT Technology
41312634's Blog, thoughts, activities, news, studies, travels, movies, cates and so on included.
首页   留言簿  订阅更新  投稿专区 
PHP发送电子邮件的方法
分类: PHP    2008-05-27 00:20:43    浏览 574    评论 0   

  PHP可以直接用mail()函数来发送邮件,但成功率不敢保证,以下是PHP使用socke方式直接发送邮件到目标地址的函数。该函数执行发送操作,如果失败则带回返回值:

//socket方式直接推送邮件
function send_mail_2($mysmtphost, $myaccount, $mypassword, $mypchost="mypc", $from_name, $from, $to, $reply_to, $subject="Hello, My Friend", $body, $charset="gb2312", $type="html") {
    $loc_host   = $mypchost;    //发信计算机名,可随意
    $smtp_acc   = $myaccount;   //Smtp认证的用户名,类似abc@123.com,或者abc
    $smtp_pass  = $mypassword;  //Smtp认证的密码,一般等同pop3密码
    $smtp_host  = $mysmtphost;  //SMTP服务器地址,类似 smtp.tom.com
    $from       = $from;        //发信人Email地址,你的发信信箱地址
                                //邮件头
    $headers    = "Mime-Version: 1.0Content-Type: text/". $type ."; charset="$charset"Content-Transfer-Encoding: base64";
    $lb         ="";                                    //linebreak

    $hdr = explode($lb,$headers);     //解析后的header
    if(!empty($body) )
    {
        $bdy = preg_replace("/^./","..",explode($lb,$body)); //解析后的Body
    }

    $smtp = array(
                //1、EHLO,期待返回220或者250
                array("EHLO ".$loc_host.$lb,"220,250","HELO error: "),
                //2、发送Auth Login,期待返回334
                array("AUTH LOGIN".$lb,"334","AUTH error:"),
                //3、发送经过Base64编码的用户名,期待返回334
                array(base64_encode($smtp_acc).$lb,"334","AUTHENTIFICATION error : "),
                //4、发送经过Base64编码的密码,期待返回235
                array(base64_encode($smtp_pass).$lb,"235","AUTHENTIFICATION error : ")
                );
    //5、发送Mail From,期待返回250
    $smtp[] = array("MAIL FROM: <".$from.">".$lb,"250","MAIL FROM error: ");
    //6、发送Rcpt To。期待返回250
    $smtp[] = array("RCPT TO: <".$to.">".$lb,"250","RCPT TO error: ");
    //7、发送DATA,期待返回354
    $smtp[] = array("DATA".$lb,"354","DATA error: ");
    //8.0、发送From
    $from_name      = "=?". $charset ."?B?". base64_encode($from_name) ."?=";
    $smtp[] = array("From: ".$from_name."<".$from.">".$lb,"","");
    //8.2、发送To
    $smtp[] = array("To: ".$to.$lb,"","");
    $reply_to = (empty($reply_to) ? $from : $reply_to);
    $smtp[] = array("Reply-To: ".$reply_to.$lb,"","");
    //8.1、发送标题
    $subject      = "=?". $charset ."?B?". base64_encode($subject) ."?=";
    $smtp[] = array("Subject: ".$subject.$lb,"","");
    //8.3、发送其他Header内容
    foreach($hdr as $h)
    {
            $smtp[] = array($h.$lb,"","");
    }
    //8.4、发送一个空行,结束Header发送
    $smtp[] = array($lb,"","");
    //8.5、发送信件主体,base64编码按定长分隔
    $body   = str_replace(".", "..", $body);
    $body   = str_split(base64_encode($body), 76);
    if($body)
    {
            foreach($body as $b)
            {
                $smtp[] = array($b.$lb,"","");
            }
    }
    //9、发送“.”表示信件结束,期待返回250
    $smtp[] = array(".".$lb,"250","DATA(end)error: ");
    //10、发送Quit,退出,期待返回221
    $smtp[] = array("QUIT".$lb,"221","QUIT error: ");

    //打开smtp服务器端口
    $fp = fsockopen($smtp_host, 25, $errno, $errstr, 30);
    if (!$fp)
    {
            $result_str = "<b>Error:</b> Cannot conect to ".$smtp_host."<br>";
            @fclose($fp);
            return $result_str;
    }
    while($result = @fgets($fp, 1024))
    {
            if(substr($result,3,1) == " ")
            {
                break;
            }
    }

    $result_str="";
    //发送smtp数组中的命令/数据
    foreach($smtp as $req)
    {
            //发送信息
            @fputs($fp, $req[0]);
            //如果需要接收服务器返回信息,则
            if($req[1])
            {
                //接收信息
                while($result = @fgets($fp, 1024))
                {
                    if(substr($result,3,1) == " ")
                    {
                        break;
                    }
                }
                if (!strstr($req[1],substr($result,0,3)))
                {
                    $result_str.=$req[2].$result."<br>";
                }
            }
    }
    //关闭连接
    @fclose($fp);
    return $result_str;
}

 

  根据本人使用smtp协议发送邮件的经验,DATA命令后,可以输入正文内容的base64编码形式,以 “回车换行.回车换行”作为结束标志,但有时base64编码形式一行过长的时候,有些web邮箱无法显示邮件正文,QQ邮箱和Sohu邮箱正是如此(2008-09-29更新该文时还是如此),解决的办法是:把正文的base64编码形式按定长来分段,例如72个字符或76个字符为一行。事实证明,按此方法修正后,我的smtp程序发送的邮件无论发到哪个邮局,均正常显示,并且没有乱码。测试邮局:hotmail、yahoo英文、yahoo中文、Gmail、QQMail、Sina、Sohu、163。

  另外,DATA命令后,From: 命令如果用到汉字,格式应该为“=?code?X?content?=”,其中code是字符编码,比如utf-8 , gb2312,X是编码规则, 一般是两种  B 表示 base64编码,  Q 表示 quote-printable编码,content是被编过的内容。例如:=?utf-8?B?6K+65pav5bid5YiG57G75L+h5oGv572R?=<nosdy_leon@sina.com>,在Foxmail客户端、Web用户端表现出来的是收件人是:诺斯帝分类信息网<nosdy_leon@sina.com>

上一篇:PHP生成指定长度的随机字符串
下一篇:广告业务方向

相关文章
[2008-05-21 11:02:23]  PHP解决截取中文子串无乱码 (670/0)
[2008-05-24 15:50:09]  PHP取客户端的IP (1022/1)
[2008-05-27 00:13:16]  PHP生成汉字图片的问题 (646/0)
[2008-05-27 00:16:50]  PHP生成指定长度的随机字符串 (642/0)
[2008-05-27 14:58:20]  PHP在线解压ZIP文件的函数 (634/0)
[2008-05-31 00:49:27]  PHP设置引起的单引号处理差异问题 (612/0)
[2008-05-31 19:08:52]  PHP控制图片自动适应 (652/0)
[2008-06-17 14:27:36]  PHP关于路径的问题 (566/0)
[2008-06-30 12:41:29]  PHP页面第一次访问时无COOKIE值 (772/0)
[2008-07-01 18:20:54]  PHP检查电子邮箱是否合法 (564/0)

本文评论列表 (0)

发表评论
姓名(*)
链接地址
Email
验证码(*) 更换验证码
评论(*) (管理员审核后公开显示)