PEAR Mail 无法连接到 Gmail SMTP,无法连接到套接字

Posted

技术标签:

【中文标题】PEAR Mail 无法连接到 Gmail SMTP,无法连接到套接字【英文标题】:PEAR Mail unable to connect to Gmail SMTP, failed to connect to socket 【发布时间】:2018-02-07 03:07:36 【问题描述】:

事实

我正在使用 PEAR Mail,我想使用 gmail SMTP 发送邮件。我有 Apache/2.4.27 (Win64) php/7.2.0beta3、PEAR 1.10.15、Mail 1.4.1、Net_SMTP 1.8.0、Net_Socket 1.2.2。

我去了php.ini并添加了extension = php_openssl.dllerror.log 没有给出与 ssl 相关的错误。

这里是代码

require_once "Mail.php";

$from = '<slevin@gmail.com>';
$to = '<slevinkelevra@gmal.com>';
$subject = 'Hi!';
$body = "Hi,\n\nHow are you?";

$headers = array(
    'From' => $from,
    'To' => $to,
    'Subject' => $subject
);

$smtp = Mail::factory('smtp', array(
        'host' => 'ssl://smtp.gmail.com',
        'port' => '465',
        'auth' => true,
        'username' => 'slevinmail@gmail.com',
        'password' => 'mypassword'
    ));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail)) 
    echo('<p>' . $mail->getMessage() . '</p>');
 else 
    echo('<p>Message successfully sent!</p>');

问题

我收到这个错误

Failed to connect to ssl://smtp.gmail.com:465 [SMTP: Failed to connect socket: fsockopen(): unable to connect to ssl://smtp.gmail.com:465 (Unknown error) (code: -1, response: )]

我不知道该怎么做,我用谷歌搜索了但我更困惑了。

请就如何解决此问题提出建议。谢谢

更新

按照 symcbean 的说明,我得到了以下结果:

bool(true) 

array(5)  
[0]=> string(31) "alt3.gmail-smtp-in.l.google.com" 
[1]=> string(26) "gmail-smtp-in.l.google.com" 
[2]=> string(31) "alt4.gmail-smtp-in.l.google.com" 
[3]=> string(31) "alt1.gmail-smtp-in.l.google.com" 
[4]=> string(31) "alt2.gmail-smtp-in.l.google.com"  
IPV4 address = 64.233.188.27

If you've got this far without errors then problem is with your SSL config

Check you've got your cacerts deployed in one of the following locations
default_cert_file = C:\Program Files\Common Files\SSL/cert.pem
default_cert_file_env = SSL_CERT_FILE
default_cert_dir = C:\Program Files\Common Files\SSL/certs
default_cert_dir_env = SSL_CERT_DIR
default_private_dir = C:\Program Files\Common Files\SSL/private
default_default_cert_area = C:\Program Files\Common Files\SSL
ini_cafile = 
ini_capath = 

If all good so far, then this bit should work....
fsockopen 
Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in C:\Apache24\htdocs\phptest2.php on line 28

Warning: fsockopen(): Failed to enable crypto in C:\Apache24\htdocs\phptest2.php on line 28

Warning: fsockopen(): unable to connect to ssl://smtp.gmail.com:465 (Unknown error) in C:\Apache24\htdocs\phptest2.php on line 28
bool(false) int(0) string(0) "" 

第28行就是这一行var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr, 3.0));

再次感谢

更新 #2

我只搜索了“fsockopen(): SSL operation failed with code 1”。的第一个警告。

结束 here 。我改变了AVG的邮件端口,就像答案一样。 symcbean 的代码运行没有错误,但我的代码回复为 mail error : authentication failure [SMTP: Invalid response code received from server (code: 534, response: 5.7.14 Please log in via your web browser and 5.7.14 then try again. 5.7.14 Learn more at 5.7.14 https://support.google.com/mail/answer/78754 c1sm1243434wre.84 - gsmtp)]

所以我用谷歌搜索了code: 534, response: 5.7.14 并最终找到了here,按照 emgh3i 第一个答案的说明,启用了不太安全的连接并允许访问我的谷歌帐户

而且它现在工作得很好。

【问题讨论】:

您必须先涉足一些命令行工具。检查openssl client 如何建立测试连接。如果失败,则可能存在某些防火墙规则。如果它只是从 Apache/PHP 失败,则使用 SELinux/AppArmor 之类的东西。 phpinfo() 显示了关于 openssl 的哪些内容? @mario 如何查看openssl client关于如何建立测试连接? @Don'tPanic openssl 部分在那里,已启用,还有库版本、标头版本、默认配置,但没有 openssl.cafileopensll.capath 的值. 会不会是防火墙,你有什么阻止互联网连接吗? 【参考方案1】:

本指南的"Use the Gmail SMTP Server" 部分说您需要enable "Less secure apps"。

【讨论】:

除了与发送邮件无关的“不太安全的应用程序”之外,您是否建议只能从 gmail 帐户向 gmail 发送电子邮件? @Don't Panic 你说的“不太安全的应用程序”是对的,但是没有必要与用户名相同,我检查了它并且工作正常。 @slevin 太好了。祝你选择正确的答案好运! :-) 我想选择你的,但我认为你应该删除 from/username 部分,因为它无关紧要,可能会误导其他人。 @symcbean 不,我没有建议,也许你误读了。我所说的是“从”与您使用的帐户不同的地址发送邮件是一个潜在的问题。 AFAIK Gmail 对任何看起来像欺骗的东西都特别敏感,尽管这似乎不是问题所在。【参考方案2】:

您的host 配置不应包含协议。它失败的原因是它可能试图在 ssl://smtp.gmail.com 上执行 DNS 查找并失败。

改变

'host' => 'ssl://smtp.gmail.com',

'host' => 'smtp.gmail.com',

【讨论】:

如果我按照你说的编辑host,年龄根本不会加载,只是挂在那里,永远不会真正加载。 ssl:// in hostname is apparently correct @Don't Panic:这是一篇关于您链接到的 codeigniter 电子邮件库的帖子,而不是 Pear::Mail。 @symcbean 是吗?该问题链接到一些 CI 代码,但他们没有说他们正在使用它。接受的答案是 PHP 处理 ssl:// 链接,而不是库或框架。另外,***.com/questions/16642346/…【参考方案3】:

你的代码是正确的

我尝试测试我的 gmail 帐户。邮件发送成功。

检查您的套接字连接

<?php

error_reporting(E_ALL);

var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr));
var_dump($errno);
var_dump($errstr);

类型(流)的资源(4)

int(0)

字符串(0) ""

【讨论】:

感谢惊人的代码,将帮助我作为调试工具。 有了这个,我收到 $errno 为 0 和 $errstr 为 ''(空)所以邮件不能使用 ssl。你能指导一下可能是什么问题吗? fsockopen 测试只知道来自 google 服务器的套接字连接在 PHP 中是可能的。如果没有socket错误,请参考其他cmets中提到的内容进行分析。【参考方案4】:

调试步骤很少:

1。检查phpinfo

我建议检查phpinfo() 以检查是否启用了所有模块。检查邮件,fsocketopen。

2。启用调试标志

启用debug 标志以准确检查问题所在。如下所示。

$smtp = Mail::factory('smtp', array(
        'host' => 'ssl://smtp.gmail.com',
        'port' => '465',
        'auth' => true,
        'debug' => true,
        'pipelining' => true,
        'username' => 'xxx@gmail.com',
        'password' => 'xxx'
    ));

在我的机器上运行上述代码后,我得到了关注响应。问题可能与您的不同。但是调试帮助了我。因为我启用了 2FA,所以它给了我错误。我也收到了一封邮件,说我的登录已被阻止。

DEBUG: Recv: 220 smtp.gmail.com ESMTP s65sm4891344pfi.36 - gsmtp DEBUG: Send: EHLO localhost DEBUG: Recv: 250-smtp.gmail.com at your service, [110.227.210.84] DEBUG: Recv: 250-SIZE 35882577 DEBUG: Recv: 250-8BITMIME DEBUG: Recv: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH DEBUG: Recv: 250-ENHANCEDSTATUSCODES DEBUG: Recv: 250-PIPELINING DEBUG: Recv: 250-CHUNKING DEBUG: Recv: 250 SMTPUTF8 DEBUG: Send: AUTH LOGIN DEBUG: Recv: 334 VsadfSFcm5hbWU6 DEBUG: Send: cGF0ZWwuZ29wYhkafdaASFnbWFpbC5jb20= DEBUG: Recv: 334 UGFzc3dvcmQ6 DEBUG: Send: OWwzMy5zaHlAbTE4 DEBUG: Recv: 534-5.7.14 Please log in via your web browser and DEBUG: Recv: 534-5.7.14 then try again. DEBUG: Recv: 534-5.7.14 Learn more at DEBUG: Recv: 534 5.7.14 https://support.google.com/mail/answer/78754 s65sm4891344pfi.36 - gsmtp DEBUG: Send: RSET DEBUG: Send: QUIT DEBUG: Recv: 250 2.1.5 Flushed s65sm4891344pfi.36 - gsmtp DEBUG: Recv: 221 2.0.0 closing connection s65sm4891344pfi.36 - gsmtp
authentication failure [SMTP: Invalid response code received from server (code: 534, response: 5.7.14 Please log in via your web browser and 5.7.14 then try again. 5.7.14 Learn more at 5.7.14 https://support.google.com/mail/answer/78754 s65sm4891344pfi.36 - gsmtp)]

更新:

您的问题看起来 PHP 甚至无法连接到 gmail 服务器。

【讨论】:

【参考方案5】:

当某些事情失败并且我们不知道原因时,我们必须进行调试。所以在这里我没有给出答案,而是要求你执行一些测试

    确认系统与互联网的连接:打开 cmd 终端并输入

    ping smtp.gmail.com
    

    确认防火墙:在 cmd 终端输入以下内容

    telnet smtp.gmail.com 465
    

    确认 php 设置:在 cmd 终端输入 php -a 并在 php 提示符下执行(复制/粘贴然后按 Enter)以下代码。

    $result = fsockopen('ssl://smtp.gmail.com', 465, $error_no, $error_message, 5);
    if ($result === false) 
      echo "error no: $error_no error message: $error_message";
      echo print_r($result, true);
     else 
      echo 'success';
    
    

    确认 Pear Mail 库和 Gmail SMTP 访问:再次在 cmd 和 php 提示符 php -a 执行您自己的代码(正如您在此线程中发布的那样)

让我们知道它在哪里中断,以及错误是什么。只有在那之后我们才能提供帮助

【讨论】:

查看我的原始帖子,更新 #2。感谢您的努力。为了记录,ping smtp.gmail 工作,但 ping telnet 回复 'telnet' is not recognized as an internal or external command, operable program or batch file. 第 3 步回复 success。第4步说:Warning: Uncaught Error: Class 'PEAR' not found in php shell code:1 Stack trace: #0 main thrown in php shell code on line 1【参考方案6】:

Been Kyung-yoong 是迄今为止唯一为解决问题做出有意义贡献的人(+1 Been!)。我可以确认他的结果。我建议你也试试。您目前正在尝试调试一个相当复杂的组件堆栈:

PEAR smtp here 抛出错误 调用Net_SMTP::connect() 时失败 这是Net_Socket::connect() 的包装 这是对fsockopen() 的相当精细的包装

Been 正在为你做你的工作 - 作为发布问题的人 - 应该创建一个 Minimal, Complete, and Verifiable example

这也有望提供更有意义的诊断信息。

失败的最可能原因是:

您运行此程序的主机无法将传出连接路由到 Internet(但由于您似乎使用的是台式电脑,我想您现在可能已经注意到了) 代码在安全沙箱中运行(但 MSWindows 并没有这样的东西) 主机无法解析主机名(参见关于路由的第一点) 主机可以连接但无法验证证书

因此您可能会考虑这种更精细的测试脚本实现:

 <?php

 error_reporting(E_ALL);

 print "DNS\n";
 var_dump(getmxrr('gmail.com',$result));
 var_dump($result);
 $use_ip=gethostbyname($result[0]);
 print "IPV4 address = $use_ip\n";

 print "\nIf you've got this far without errors then problem is with your SSL config\n";
 $calocns=openssl_get_cert_locations();
 if (count($calocns)) 
     print "Check you've got your cacerts deployed in one of the following locations\n";
     foreach ($calocns as $k=>$v) print "$k = $v\n";
  else 
     print "You've not configured your openssl installation on this host\n";
 

 print "\nIf all good so far, then this bit should work....\n";
 print "fsockopen\n";
 var_dump(fsockopen("ssl://smtp.gmail.com", 465, $errno, $errstr, 3.0));
 var_dump($errno);
 var_dump($errstr);

这应该会给你这样的回应:

 DNS
 bool(true)
 array(5) 
   [0]=>
   string(31) "alt1.gmail-smtp-in.l.google.com"
   [1]=>
   string(31) "alt2.gmail-smtp-in.l.google.com"
   [2]=>
   string(31) "alt4.gmail-smtp-in.l.google.com"
   [3]=>
   string(26) "gmail-smtp-in.l.google.com"
   [4]=>
   string(31) "alt3.gmail-smtp-in.l.google.com"
 
 IPV4 address = 74.125.131.26

 If you've got this far without errors then problem is with your SSL config
 Check you've got your cacerts deployed in one of the following locations
 default_cert_file = /usr/lib/ssl/cert.pem
 default_cert_file_env = SSL_CERT_FILE
 default_cert_dir = /usr/lib/ssl/certs
 default_cert_dir_env = SSL_CERT_DIR
 default_private_dir = /usr/lib/ssl/private
 default_default_cert_area = /usr/lib/ssl
 ini_cafile =
 ini_capath =

 If all good so far, then this bit should work....
 fsockopen
 resource(4) of type (stream)
 int(0)
 string(0) ""

鉴于我们无法复制您的错误,我们无法给出明确的答案 - 但我的猜测是you haven't configure openSSL。

【讨论】:

感谢您的惊人努力。在更新部分查看我的原始帖子以获取结果。请记住,我是一个“后端新手”(如果这甚至是一个术语),所以请指教。我无法得到关于我应该如何进行或下一步应该做什么的提示。再次感谢 “证书验证失败” - 因此您与 smtp.gmail.com 的连接正在被 MITMed(不太可能)或您的 cacerts 未安装/最新。您可以在此处以正确的格式获取当前 Mozilla 策划的 CACert 包:curl.haxx.se/docs/caextract.html 查看我的原始帖子,更新 #2。那么,这毕竟是 gmail 部分的问题吗?再次感谢 我的意思是连接是 由您的 AV 产品提供的 MITM 。它无法读取加密流,因此它会对其进行解密,然后将其重新加密回您的应用程序。当您安装它时,它会将自己的 CAcert 注入 Microsoft 证书存储区,因此任何使用该证书的应用程序都会认为该证书很好 - 但它不会知道 OpenSSL CAcert 文件。 @symvbean, 'Been Kyung-yoong 是唯一做出有意义贡献的人'......你的社论侮辱了那些给出正确答案的人,这与你的想法无关问题是。【参考方案7】:

在我开始之前,让我先说明一下,您的服务器和谷歌服务器之间有许多可能的解决方案和结果,因此这些可能适用于不同的人,也可能不适用于不同的人。

1) SMTP 不是很安全,因此 Google 可能会拒绝您的请求。我在 6 个月前遇到了这个问题,解决方案是在“myaccount.google.com”下启用不安全的应用

2)如果这对您不起作用,那么您可以考虑切换协议。

来自

'host' =&gt; 'ssl://smtp.gmail.com',

'host' =&gt; 'tls://smtp.gmail.com:587';

【讨论】:

“SMTP 不是很安全”——它并不是为了保证安全——这就是 AUTH、STARTTLS 和 SMTPS 的意义所在。 “允许安全性较低的应用程序”的配置选项仅启用 IMAPS 连接以及在邮箱上启用基本身份验证 - 与发送邮件无关。 @symcbean。我的答案是正确的。它实际上为我自己和 slevin 解决了这个问题。【参考方案8】:

在 PHP 5.3 中,其他人给出的关于“不太安全的应用程序”的提示解决了我所有的问题。

在 PHP 7.2 中我必须做更多:将 'auth' 设置为 PLAIN,然后为 ssl socket_options 添加“verify_peer”和 verify_peer_name,如下所示:

$mail= Mail::factory('smtp', array('host' => 'ssl://smtp.gmail.com',
                                   'port' => '465',
                                   'auth' => 'PLAIN',
                                   'socket_options' => array('ssl' => array('verify_peer' => false,
                                                                            'verify_peer_name' => false)),
                                   'username' => 'someAccount@gmail.com',
                                   'password' => 'myPassword'
));

【讨论】:

【参考方案9】:

这可能与问题没有直接关系,但对于通过远程服务器使用 Pear SMTP 发送电子邮件时遇到问题的任何人,真正的问题不是防火墙配置而是 SELINUX。如果它打开(这是默认设置),您可能会花几天时间想知道为什么权限被拒绝。只需告诉 selinux 允许 apache 发送电子邮件:

setsebool -P httpd_can_sendmail 1

我希望这可以为某人省去麻烦。

【讨论】:

以上是关于PEAR Mail 无法连接到 Gmail SMTP,无法连接到套接字的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Java 连接到我的 Gmail 收件箱

尝试连接到 gmail IMAP 服务器时出现 javax.mail.MessagingException

Flask-Mail 尝试连接到 Gmail 时超时

Spring Boot - 无法连接到 SMTP 主机:smtp.gmail.com,端口:25,响应:421

PHP Pear Mail 返回致命错误:无法打开所需的“Mail.php”

无法发送电子邮件至smtp.gmail.com