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

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

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

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

但是,由于gmail的smtp采用了ssl连接:

Outgoing Mail (SMTP) Server – requires TLS: smtp.gmail.com (use authentication) Use Authentication: Yes Use STARTTLS: Yes (some clients call this SSL) Port: 465 or 587

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

修改class.smtp.php,第101行,把

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

改成

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

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

extension=php_openssl.dll

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

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

$this->smtp->do_debug = $this->SMTPDebug; $hosts = explode(“;”, $this->Host); $index = 0; $connection = ($this->smtp->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; }

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

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

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

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

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

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

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

function send_mail($to_address, $to_name ,$subject, $body, $attach = ”) { //使用phpmailer发送邮件 require_once(“phpmailer/class.phpmailer.php”); $mail = new PHPMailer(); $mail->IsSMTP(); // set mailer to use SMTP $mail->CharSet = ‘utf-8′; $mail->Encoding = ‘base64′; $mail->From = ‘fwolf.mailagent@gmail.com’; $mail->FromName = ‘Fwolf’; //$mail->Sender = ‘fwolf.mailagent@gmail.com’; //$mail->ConfirmReadingTo = ‘fwolf.mailagent@gmail.com’; //回执? $mail->Host = ‘ssl://smtp.gmail.com’; $mail->Port = 465; //default is 25, gmail is 465 or 587 $mail->SMTPAuth = true; $mail->Username = “fwolf.mailagent@gmail.com”; $mail->Password = “xxx”; $mail->>ddAddress($to_address, $to_name); //$mail->AddReplyTo(‘fwolf.mailagent@gmail.com’, “Fwolf”); //针对gmail无用,gmail是In-Reply-To:,phpmailer默认生成的是Reply-to: $mail->WordWrap = 50; if (!empty($attach)) $mail->AddAttachment($attach); $mail->IsHTML(false); $mail->Subject = $subject; $mail->Body = $body; //$mail->AltBody = “This is the body in plain text for non-HTML mail clients”; if(!$mail->Send()) { echo “Mail send failed.\r\n”; echo “Error message: ” . $mail->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.smtp.php的1024行): 将:

fgets($this->smtp_conn,515)

改为:

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

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

Update @ 2008-04-14

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

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

Related posts

Categories: PHP Tags: , , , , ,
  1. Richard
    May 20th, 2007 at 01:32 | #1

    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

  2. May 20th, 2007 at 15:31 | #2

    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

  3. btdf007
    July 20th, 2007 at 14:07 | #3
    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

  4. July 20th, 2007 at 14:46 | #4

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

    Reply

  5. geinizhi
    August 11th, 2007 at 04:37 | #5

    谢谢楼主的文章。我照猫画虎地试了一下,但是总是得到如下信息: 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

  6. August 11th, 2007 at 11:30 | #6

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

    Reply

  7. geinizhi
    August 11th, 2007 at 13:54 | #7

    谢博主这是我用的代码:

    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

  8. August 11th, 2007 at 23:22 | #8

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

    Reply

  9. geinizhi
    August 12th, 2007 at 01:32 | #9

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

    Reply

  10. October 13th, 2007 at 02:17 | #10

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

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

    可以完成以上工作

    Reply

  11. lein
    December 25th, 2007 at 11:33 | #11

    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

  12. tandm
    December 31st, 2007 at 21:27 | #12

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

    Reply

  13. December 31st, 2007 at 22:48 | #13

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

    Reply

  14. March 12th, 2008 at 10:38 | #14

    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

  15. March 13th, 2008 at 23:15 | #15

    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

  16. kent
    April 11th, 2008 at 11:32 | #16

    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

  17. April 11th, 2008 at 13:24 | #17

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

    Reply

  18. 可乐
    July 9th, 2009 at 15:45 | #18

    昨天还没问题,今天这个phpmailer忽然不能使用gmail的ssmtp发邮件了,总是socket超时,普通的邮件软件没问题.

    Reply

Comment pages
1 2 155
  1. June 8th, 2006 at 07:04 | #1
  2. July 11th, 2006 at 23:49 | #2
  3. September 14th, 2006 at 15:10 | #3
  4. September 22nd, 2006 at 21:39 | #4
  5. September 28th, 2006 at 10:07 | #5
  6. October 23rd, 2006 at 18:07 | #6
  7. September 27th, 2007 at 18:19 | #7
  8. November 30th, 2007 at 23:27 | #8
  9. October 8th, 2008 at 13:11 | #9
  10. October 8th, 2008 at 16:33 | #10
  11. October 14th, 2008 at 22:48 | #11
  12. January 3rd, 2009 at 21:47 | #12