zoukankan      html  css  js  c++  java
  • PHPMailer不能发送邮件

    PHPMailer不能连接SMTP服务器,和修改SMTP大小写没有关系

    (2011-10-22 12:17:35)

    转载▼

    标签:

    php

    phpmailer

    杂谈

    分类: 默认分类

    PHPmailer无法发送邮件,提示错误Error: Could not connect to SMTP host

    博客之前有两篇文章,《PHPMailer::不能连接SMTP服务器》《PHPMailer不能连接SMTP服务器的两种常见原因
    一为转载,一为笔记,结果误人子弟了,不是每个人能解决问题。
    有朋友来信求助,我也着急。虽然后来解决了,但我还是不得要领,静下心来又看了看

    PHPMailer不能连接SMTP服务器,究竟为什么?先用代码检测一下:

    <?
    function Get_host($host){  //解析域名
    $Get_host=gethostbyname($host);
    echo "尝试连接 $host ...<br>  ";
    if(!$Get_host){
    $str= "解析失败 (1)<HR>";
    }elseif($Get_host==$host){
    $str= "解析失败 (2): 可能是一个无效的主机名<HR>";
    }else{
    echo "域名解析为 $Get_host ...<br> ";
    Open_host($host);}
    echo $str;
    }

    Function Open_host($host){  //连接主机

    if(function_exists('fsockopen')){
    $fp = fsockopen($host,25,&$errno,&$errstr,60);
      elseif(function_exists('pfsockopen')){
        echo "服务器不支持Fsockopen,尝试pFsockopen函数 ...<br> ";
        $fp = pfsockopen($host,25,&$errno,&$errstr,60); }
      else
        exit('服务器不支持Fsockopen函数');

    if(!$fp){
    echo "代号:$errno,<br> 错误原因:$errstr<HR>";
    }else{
    echo "SMTP服务器连接ok!<br> ";
    fwrite($fp, "");
    $out0= fgets($fp, 128);
    #echo $out0;
    if (strncmp($out0,"220",3)==0){ // 判断三位字符内容
    echo '220 SMTP服务端响应正常<HR>';
    }else{
    echo '服务器端错误<HR>';}
    }
    }
    //SMTP服务器地址
    $site = array("smtp.163.com","smtp.sina.cn","smtp.sina.com","smtp.qqq.com","smtp.126.com");

    //调运脚本
    #$host="smtp.163.com";
    #echo Get_host($host);


    for ($i=0; $i<=4; $i++)
    {  
    $host= $site[$i];
     echo Get_host($host);
    }



    PHPmailer是一个非常棒的PHP发送mail类,处理错误则侧重于和SMTP服务器会话过程中的问题,比如身份验证不对、收件人为空的错误提示,但是对于连接到smtp过程的错误提示以“Could not connect to SMTP host”一言蔽之,导致了很多问题没能解决,更可笑的是导致一些有用却讲不出道理的方法流传于世,可见,冥冥中一切皆有定数。

    好了,不说口水话了。
    想要搞清楚Could not connect to SMTP host的原因,自然要明白连接服务的步骤
    一次完整有效的SMTP发信过程应该包括:解析域名、连接SMTP服务器、验证身份、确定收件人和信件内容、发送

    上面那段PHP代码就是把这几个步骤分开来做,找出原因,然后寻找方法。回显的结果大概有如下几种:

    1、解析失败 (2): 可能是一个无效的主机名
    说明域名无法解析。可能是DNS级别的问题。联系管理员或者更换服务商

    2、服务器不支持Fsockopen,尝试pFsockopen函数
    如果用pfsockopen函数连接服务器成功了,则修改class.smtp.php 的$this->smtp_conn = fsockopen( 为$this->smtp_conn = pfsockopen( 。使PHPmailer恢复正常使用

    3、服务器端错误
    成功和远程主机建立连接,不过对方没有安装SMTP协议发送220响应码,说明SMTP服务器可能有问题

    4、220 SMTP服务端响应正常

    好吧,不论是fsockopen函数还是pfsockopen函数,已经和远程的SMTP服务器正常连接了。如果是无法用PHPmailer发信,我强烈建议你换一个账号重新试一下

    5、其他报错,比如这样

    Warning: fsockopen(): unable to connect to smtp163.com:25
    你绝对有理由相信是防火墙搞的鬼! 这种情况下,如果不能联系管理员改防火墙规则 你可以试试《PHPMailer::不能连接SMTP服务器》中的方法,
    搜索
    function IsSMTP() {
    $this->Mailer = 'smtp';
    }

    改成:
    function IsSMTP() {
    $this->Mailer = 'SMTP';
    }

    正如我标题所言“PHPMailer不能连接SMTP服务器,和修改SMTP大小写没有关系”。当然我不可能恶趣味的作弄你,而是有时候真的有效,治愈成功率多大就看你的人品了

    来分析一下原因吧。
    这句代码大概在class.phpmailer.php286行左右。这个函数在使用PHPmailer类时要首先调用,用以声明发送mail的方式

    跟踪this->Mailer 到 class.smtp.php 400行左右 

    switch($this->Mailer) {
          case 'sendmail':
            $result = $this->SendmailSend($header, $body);
            break;
          case 'smtp':
            $result = $this->SmtpSend($header, $body);
            break;
          case 'mail':
            $result = $this->MailSend($header, $body);
            break;
          default:
            $result = $this->MailSend($header, $body);
            break;

    首先smtp绝对不等于SMTP!这一基本原则我居然都会忘掉。
    所以,上面的条件都不满足 PHPmailer将执行 $result = $this->MailSend($header, $body);这句

    再来跟踪MailSend()函数 在class.phpmailer.php 460行左右:

      function MailSend($header, $body) {
        $to = '';
        for($i = 0; $i < count($this->to); $i++) {
          if($i != 0) { $to .= ', '; }
          $to .= $this->AddrFormat($this->to[$i]);
        }

        $toArr = split(',', $to);

        $params = sprintf("-oi -f %s", $this->Sender);
        if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {
          $old_from = ini_get('sendmail_from');
          ini_set('sendmail_from', $this->Sender);
          if ($this->SingleTo === true && count($toArr) > 1) {
            foreach ($toArr as $key => $val) {
              $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
            }
          } else {
            $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
          }
        } else {
          if ($this->SingleTo === true && count($toArr) > 1) {
            foreach ($toArr as $key => $val) {
              $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
            }
          } else {
            $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
          }
        }

        if (isset($old_from)) {
          ini_set('sendmail_from', $old_from);
        }

        if(!$rt) {
          $this->SetError($this->Lang('instantiate'));
          return false;
        }

        return true;
      }


    注意$rt = @mail( 这是用PHP内置的mail函数发信啊!


    来自W3School的mail发信实例

    <?php
    $to = "somebody@example.com"; //这里改成你的邮箱地址
    $subject = "My subject";
    $txt = "Hello world!";
    $headers = "From: dongfangtianyu@qq.com" . " " .
    mail($to,$subject,$txt,$headers);
    ?>


    如果在你的服务器上运行这脚本能够收到邮件,那么你完全可以用修改SMTP大小写的方法。不过,毕竟不大好用

    .


    想要使用mail函数函数发信,需要修改设置php.ini,也即是说,成与不成得看你的服务提供商。
    如果服务器已经设置好了mail()相关的一切,PHPmailer使用mail()的方法当然可以发信成功。不再依赖fsockopen函数

    这也就是为什么防火墙禁止的情况下,用修改smtp大小写反而能用PHPmailer发信,因为那封e-mail根本是用本地的smtp服务器代发的
    亲爱的朋友,你明白了吗?

     

  • 相关阅读:
    Django模型层Meta内部类详解
    jquery checkbox的相关操作——全选、反选、获得所有选中的checkbox
    c# 委托与异步调用
    DataTable转成List集合
    c# winform 自动升级
    C# winform单元格的formatted值的类型错误 DataGridView中CheckBox列运行时候System.FormatException异常
    C#创建无窗体的应用程序
    sql 一个表的字段更新至另一个字段的方法
    datagridview 获取选中行的索引
    CHECKEDLISTBOX用法总结
  • 原文地址:https://www.cnblogs.com/yingjie13/p/4105567.html
Copyright © 2011-2022 走看看