终于能够通过phpmailer使用gmail账号发送邮件了

授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/155)的形式标明文章原始出处和作者信息及本声明。

phpmailer(现在的版本是1.73)是一个很好用的工具,可以很方便的使用语言发送邮件,支持及验证,我们一直都用它。

但是,由于采用了连接:

Outgoing () Server - requires TLS: ..com (use authentication)
Use Authentication: Yes
Use STARTTLS: Yes (some clients call this )
Port: 465 or 587

使用就无法正常连接的发信服务器了,并且这个问题一直没有得到的官方解决,不过在sf.net上面的讨论里倒是找到了一点资料,采用下面这种方法就可以连接了。

修改class..,第101行,把

$this->smtp_conn = fsockopen($host, # the host of the server

改成

$this->smtp_conn = fsockopen(’://’ . $host, # the host of the server

这样就可以了,就是指定使用协议连接主机,当然的openssl模块必须打开:

extension=php_openssl.dll

但是这样就不能使用非的主机了,我也不像在include目录下面放两份,于是,又琢磨出了一种更好的方式:

打开class..,在大概543行附近,函数SmtpConnect()中,找到:

$this->->do_debug = $this->SMTPDebug;
$hosts = explode(”;”, $this->Host);
$index = 0;
$connection = ($this->->Connected());

// Retry while there is no connection
while($index < count($hosts) && $connection == false)
{
if(strstr($hosts[$index], ":"))
list($host, $port) = explode(":", $hosts[$index]);
else
{
$host = $hosts[$index];
$port = $this->Port;
}

这一段的部分功能就是,如果你输入的主机名中带有端口号,自动的识别出来,设想虽好,但就是这部分让我们无法直接在调用的时候使用格式的主机名,因为“://xxx”的形式会被误认为是主机:端口号的形式,另外端口号一般都比较固定,我们手工设置好了,也不必一定要和主机一起赋值,所以在上面的代码后面添加:

//Modify by Fwolf @ 2006-4-14, to enable connection
$host = $this->Host;
$port = $this->Port;

就可以了,使用正常主机的时候,用法不变,使用的时候,使用://..com作为主机名就可以了,唯一稍微麻烦一些的就是端口需要手工指定——其实也不麻烦。

按照上面的配置更改后,使用账号发送邮件时还会有一条警告信息:

Warning: fgets(): : fatal protocol error in H:\php_includes\phpmailer_ssl\cla
ss.. on line 1024

这各警告信息在php的帮助里面有,好像是在使用连接的时候,读文件读到文件尾的时候出现的问题,需要手工屏蔽,或者人为控制读的长度,我们用最简单的方式禁止警告信息显示就可以了,找到class..的1024行,在fgets($this->smtp_conn,515)函数前面加上个@就可以了。

下面是一个完整的使用发送邮件的函数:

function send_mail($to_address, $to_name ,$subject, $body, $attach = ”)
{
//使用发送邮件
require_once(”/class..”);
$ = new ();
$->IsSMTP(); // set mailer to use
$->CharSet = ‘utf-8′;
$->Encoding = ‘base64′;
$->From = ‘fwolf.mailagent@.com’;
$->FromName = ‘Fwolf’;
//$->Sender = ‘fwolf.mailagent@.com’;
//$->ConfirmReadingTo = ‘fwolf.mailagent@.com’; //回执?

$->Host = ’://..com’;
$->Port = 465; //default is 25, is 465 or 587
$->SMTPAuth = true;
$->Username = “fwolf.mailagent@.com”;
$->Password = “xxx”;

$->>ddAddress($to_address, $to_name);
//$->AddReplyTo(’fwolf.mailagent@.com’, “Fwolf”); //针对无用,是In-Reply-To:,默认生成的是Reply-to:
$->WordWrap = 50;
if (!empty($attach))
$->AddAttachment($attach);
$->IsHTML(false);
$->Subject = $subject;
$->Body = $body;
//$->AltBody = “This is the body in plain text for non-HTML clients”;

if(!$->Send())
{
echo “ send failed.\r\n”;
echo “Error message: ” . $->ErrorInfo . “\r\n”;
return false;
}
else
{
echo(”Send $attach to $to_name <$to_address> successed.\r\n”);
return true;
}
//echo “Message has been sent”;
//
}

update @ 2006-11-3

感谢RainChen提供的fgets出错提示的更好解决办法(位置大概在class..的1024行):
将:

fgets($this->smtp_conn,515)

改为:

!feof($this->smtp_conn) && $str = fgets($this->smtp_conn,515)

这样的代码就规范多了,极力不提倡使用@来屏蔽错误信息。
(未测试, 但有网友反映这种改法是不行的)

Update @ 2008-04-14

试了最新的 2.1.0 Beta 2,不用作任何修改,就可以用账号发送邮件了,官方文档中还给出了例子,和我用的方法不太一样。

不过中文附件的问题依然没有解决,需要自己hack。

Tags: , , , , ,

Related posts

45 Responses to “终于能够通过phpmailer使用gmail账号发送邮件了”

  1. StartMenu Says:

    收信又怎么办呢?
    老不成功。
    我从一个php邮件系统中挖出来的收pop3的代码。
    收其他的,如163,sohu的都完全正常。

    [Reply]

  2. PHPMailer con GMail Says:

    [...] En un hilo publicado en forosdelweb, en el que un usuario desea utilizar el servidor SMTP de GMail para enviar correos usando PHPMailer, hacen referencia a esta interesante entrada que sirve justamente para lo antes mencionado. [...]

  3. Renew » Blog Archive » phpmailer使用gmail SMTP的方法 Says:

    [...] http://www.fwolf.com/blog/post/155 [...]

  4. SG Says:

    用了你的方法, 但出现:

    Warning: fsockopen() [function.fsockopen]: unable to connect to ssl://smtp.gmail.com:465 (Unable to find the socket transport “ssl” - did you forget to enable it when you configured PHP?) in D:\www\phpgmailer\class.smtp.php on line 105
    Message was not sent

    Mailer Error: SMTP Error: Could not connect to SMTP host.

    什么没改过来?

    [Reply]

  5. Fwolf Says:

    楼上的,要使用ssl协议,php必须启用openssl扩展才行。

    [Reply]

  6. york Says:

    为什么我试的时候说 no SSL support in this build in
    但是apache的ssl已经可以用了,php中的php_openssl.dll开启用了。

    [Reply]

  7. Fwolf Says:

    no SSL support in this build in
    感觉还是php的openssl没有正确启用
    另外再检查一下php的errorlog,看看有没有其他的原因,记得开error E_ALL
    一般都能找到有用的信息的

    [Reply]

  8. York Says:

    问题找到了,是php 4.3.x 版本的openssl的问题。需要下载新的php4ts.dll,并替换掉原来的php4ts.dll。

    http://bulaoge.com/topic.blg?dmn=webdev&tid=117221#Content

    [Reply]

  9. JL空间 Says:

    终于能够通过phpmailer使用gmail账号发送邮件了…

    原文联接: http://www.fwolf.com/blog/post/155终于能够通过phpmailer使用gmail账号发送邮件了授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/155)的形式标明文…

  10. 我好晕啊 Says:

    Hi, I tried your method.
    But it doesn’t work.
    There’s another package can be used.
    XPM2

    [Reply]

  11. 石头记 » 通过phpmailer使用gmail账号发送邮件 Says:

    [...] Fwolf’s Blog by Kevin Pilgrim | 发表在 技术资料, PHP Trackback URL | Comment RSS Feed del.icio.us上的标签 | 进入的链接 [...]

  12. 通过phpmailer发送邮件的用法 at 独伫小桥听风雨 Says:

    [...] 原文联接: http://www.fwolf.com/blog/post/155 [...]

  13. popo Says:

    我用了,可以发送邮件。但是感觉很慢,比普通的smtp连接,明显感觉慢很多。
    但是也有问题:
    warning: fgets(): SSL: fatal protocol error in /var/www/pages/drupal-4.7.3/includes/phpmailer/class.smtp.php on line 1024.

    这个警告我一直去不掉。我在前面加了@还是不行。 每次发邮件都有错误,很不好啊。
    我的php.ini也设置了不显示错误的啊。

    [Reply]

  14. Fwolf Says:

    to popo: 两点感觉:
    1、似乎openssl或者ssl协议支持的其他地方没有安装或者设置正确
    2、php.ini是不是没有正确启用(这一点会同时影响到1)?如果是用命令行执行的话,有时候使用的是另外一个php.ini文件,和apache使用的不是一个文件,这一点至少在ubuntu里面是的。

    [Reply]

  15. popo Says:

    phpinfo() 显示
    Configuration File (php.ini) Path /etc/php.ini (正确)
    ….
    openssl
    OpenSSL support enabled
    OpenSSL Version OpenSSL 0.9.8c 05 Sep 2006

    而且我的确是能发出信的啊,这个说明确实是openssl启用啊。

    /etc/php.ini 设置
    display_errors = Off
    log_errors = On
    error_log = /var/log/php.error.log

    还是不能用。
    哦,我明白了,你是windows,我是linux。

    [Reply]

  16. Fwolf Says:

    我现在在linux下用也是可以的
    你的@加的位置对不对?

    [Reply]

  17. Speed is Fun» Blog Archive » phpmailer插件对gmail的支持方法 Says:

    [...] 授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/155)的形式标明文章原始出处和作者信息及本声明。 [...]

  18. RainChen Says:

    fgets的修改建议改为:
    将:
    fgets($this->smtp_conn,515)
    改为:
    !feof($this->smtp_conn) && $str = fgets($this->smtp_conn,515)

    这样才是比较smooth的hack

    [Reply]

  19. zerofault Says:

    to rainchen:
    我用照你的改了,可是还是老错误

    to SG:
    不知道你用的php哪个版本,我用的是php5.2.0,发现只在php.ini里取消opensl前的注释是不够的,还应该复制php目录下的ssleay32.dll和libeasy32.dll到你的windows\system32目录下

    to 博主:
    你的介绍很有用,谢谢
    不过你也没有把怎么打开openssl说清楚,至少我是花了半天时间来启动openssl功能,而且在php4.4.*版本上还没成功.

    [Reply]

  20. Fwolf Says:

    To zerofault:
    openssl的启用说明在php的手册上说的很清楚,你没有去查么?:)
    我在很久以前遇到过这个问题,不过现在已经比较熟悉了
    所以没有介绍,所以还要谢谢你的补充。

    [Reply]

  21. soitif Says:

    比如发是用,soitif@gmail.com
    可是我想让From=soitif@163.com
    这样他们点回复直接是回复到soitif@163.com
    这个还有什么办法吗?

    [Reply]

  22. Fwolf Says:

    to soitif:
    除了设置Reply-to(即使用AddReplyTo函数)以外,
    很少邮件服务器允许你伪装from信息,因为容易被坏人利用
    一般情况下能够指定回信地址应该就足够用了。

    [Reply]

  23. kukukuan Says:

    !feof($this->smtp_conn) && $str = fgets($this->smtp_conn,515)
    在我这里测试未通过,PHP版本5.1.2

    [Reply]

  24. kukukuan Says:

    根据你提示的内容,改了一下,已经可以不单独指定端口了
    办法是用正则表达式匹配代替explode,详情见
    http://blog.gmap2.net/2007/03/18/let-phpmailer-support-gmail/

    [Reply]

  25. bill Says:

    谢谢分享。

    [Reply]

  26. Fwolf Says:

    楼上的楼上(kukukuan)提供的地址如果无法访问的话(我就是),可以试试
    http://blog.gmap2.net/2007/03/18/
    这个地址,文中用explode的方式虽然没有测试过,但理论上应该是可行并且更好一点的解决方法
    能夠直接让phpmailer的作者这样更新就更好了 :)。

    [Reply]

  27. Richard Says:

    Hi, sorry I dont speak chinese.

    when I use your example from a gmail account works fine,

    $mail->Host = ’ssl://smtp.gmail.com’;
    $mail->Port = 465; //default is 25, gmail is 465 or 587

    I have my mail hosted in a google account, it use TLS instead of SSL and port 587
    then

    $mail->Host = ’tls://smtp.gmail.com’;
    $mail->Port = 587;
    $mail->Username =’me@mydomain.com’;
    $mail->Password = ‘mypass’;

    GET Error: Language string failed to load: connect_host

    Is there an special configuration for mails hosted on google (NO GMAIL) ?

    Thanks, richard

    [Reply]

  28. Fwolf Says:

    To: Richard
    I think they work in the same way, have you try change tls: to ssl ?
    465 for ssl do same thing to 587 for tls,
    I have tried in my google apps, just notice below settings, it works fine:

    $mail->From = 'me@mydomain.com';
    ...
    $mail->Host = 'ssl://smtp.gmail.com';
    $mail->Port = 465;
    ...
    $mail->Username = "me@mydomain.com";
    

    [Reply]

  29. btdf007 Says:
    1. 为什么会出现这种错误总
      Warning: fgets() [function.fgets]: SSL operation failed with code 1. OpenSSL Error messages: error:1408F10B:SSL routines:func(143):reason(267) in D:serverwampwwwtempphpmailerclass.smtp.php on line 1024
    2. gmail的 邮箱不能受到 但是 163的邮箱可以 为什么?

    class.stmp.php这样改没错吧?

    function get_lines() {
    $data = “”;
    while(!feof($this->smtp_conn) && $str = fgets($this->smtp_conn,515)) {
    if($this->do_debug >= 4) {
    echo “SMTP -> get_lines(): $data was \”$data\”" .
    $this->CRLF;
    echo “SMTP -> get_lines(): $str is \”$str\”" .
    $this->CRLF;
    }

    [Reply]

  30. Fwolf Says:

    你的主机可能不支持openssl,
    也就是说ssl客户端没有安装

    [Reply]

  31. geinizhi Says:

    谢谢楼主的文章。我照猫画虎地试了一下,但是总是得到如下信息:
    SMTP -> FROM SERVER: SMTP -> FROM SERVER: SMTP -> ERROR: EHLO not accepted from server: SMTP -> FROM SERVER: SMTP -> ERROR: HELO not accepted from server: SMTP -> ERROR: AUTH not accepted from server: SMTP -> NOTICE: EOF caught while checking if connected
    The following From address failed: xxx@gmail.com
    什么地方错了吗?

    [Reply]

  32. Fwolf Says:

    @geinizhe 好像是连接被服务器拒绝了,检查你向服务器提供的各个参数是否正确。

    [Reply]

  33. geinizhi Says:

    谢博主这是我用的代码:

    require(”class.phpmailer.php”);
    $mail = new PHPMailer();
    $mail->IsSMTP(); // telling the class to use SMTP
    $mail->SMTPDebug = true;
    $mail->Host = ’smtp.gmail.com’; // SMTP server 注:我在class.smtp.php里加了’ssl://’。因为我加在这里的话总是”can not connect smtp server”
    $mail->Port = 465;
    $mail->SMTPAuth = true; // turn on SMTP authentication
    $mail->Username = “xxx@gmail.com”; // SMTP username
    $mail->Password = “xxx”;

    $mail->From = “xxx@gmail.com”;
    $mail->FromName = “xxx”;
    $mail->AddAddress(”xxx@mydomain.com”);

    $mail->Subject = “test msg”;
    $mail->Body = “hi, this is a test msg”;

    $mail->Send();

    请博主和大家指正。另外,我的HOSTING说我遇到的问题和他们没有关系。

    [Reply]

  34. Fwolf Says:

    @geinizhi 我用你的代码发邮件正常,可疑之处就是
    $mail->SMTPDebug = true;这一句,可以去掉。

    [Reply]

  35. geinizhi Says:

    我改用swiftmail。现在可以了。 :)

    [Reply]

  36. Sol的资料室 » 终于能够通过phpmailer使用gmail账号发送邮件了 Says:

    [...] 授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/155)的形式标明文章原始出处和作者信息及本声明。 phpmailer(现在的版本是1.73)是一个很好用的工具,可以很方便的使用php语言发送邮件,支持smtp及验证,我们一直都用它。 [...]

  37. nobody Says:

    $mail->Host = urlencode(’ssl://smtp.gmail.com’);

    $this->smtp_conn = fsockopen( urldecode($host) …

    可以完成以上工作

    [Reply]

  38. PHPMailer 类综合应用 | 白板博客 Says:

    [...] 阅读文章:终于能够通过phpmailer使用gmail账号发送邮件了 [...]

  39. lein Says:

    function get_lines() {
    $data = “”;
    stream_set_timeout($this->smtp_conn,25);
    while(!feof($this->smtp_conn) && $str = fgets($this->smtp_conn,515)) {
    if($this->do_debug >= 4) {
    echo “SMTP -> get_lines(): $data was \”$data\”" .
    $this->CRLF;
    echo “SMTP -> get_lines(): $str is \”$str\”" .
    $this->CRLF;
    }
    $data .= $str;
    if($this->do_debug >= 4) {
    echo “SMTP -> get_lines(): $data is \”$data\”" . $this->CRLF;
    }
    # if the 4th character is a space then we are done reading
    # so just break the loop
    if(substr($str,3,1) == ” “) { break; }
    }
    $info = stream_get_meta_data($this->smtp_conn);
    if ($info['timed_out']) {
    echo ‘Connection timed out!’;
    }
    return $data;
    }
    这样即使超时感觉也要好一些.

    [Reply]

  40. tandm Says:

    楼主,你好,我看了你们的修改方法,我完全是按照操作来的,还是不能不过,急死人了。
    麻烦楼主能否把一个代码实例发送到我的邮箱:tandm@163.com,非常感激。

    [Reply]

  41. Fwolf Says:

    phpmailer的新版好像已经支持gmail邮件发送了,你去试试吧。
    我这里只卖渔,不卖鱼。

    [Reply]

  42. Yurtdisi Egitim Says:

    it seems like e very good web site but my Chinese is not good. It would be great if it might be availible in English too. Thanks.

    [Reply]

  43. Fwolf Says:

    Chinese is my mother language, so if you need english version or some relate information,
    I’ll happy to provide with email, because obviously I have no enough time to translate them all to english. :-)

    [Reply]

  44. kent Says:

    i follow your steps
    but i cant work
    it always say
    no SSL support in this build in class.stmp.php line 122
    can you help me to fix it?

    [Reply]

  45. Fwolf Says:

    @kent
    You need to enable openssl extension of php,
    or compile your php with openssl enabled.

    [Reply]

Leave a Reply

您的留言将被缓存和审阅,所以不会立即出现在这里,请别着急,着急的话可以给我发邮件 :-)
支持Markdown Extra语法,参见: [甲] [1] [2]