[SMTP:无法连接套接字:fsockopen():无法连接到 ssl://smtp.gmail.com:465(未知错误)(代码:-1,响应:)]

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

过去两个月我一直在解决这个问题,但没有找到解决方法。我正在使用 PHP 5.6.3 和 PEAR 1.10.1,有问题的电子邮件页面与我们本地服务器上的 3 方电子邮件软件一起工作正常,仅设计用于 SMTP 端口 25。现在 PHP 页面确实引用了包含所有主机、密码和用户名信息的 XML 模板。我想切换到使用带有 SSL 的 google 电子邮件服务器。我实施了我的电子邮件管理员提供的更改并相应地更改了 MX 记录。它正常运行了两个星期。之后我收到以下错误

"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: )]".

我更改了几次代码,删除了 ssl://,将协议类型更改为端口号为 587 的 TLS 等。没有任何效果!我联系了承包商构建一个简单的硬编码页面,该页面只是使用 gmail 服务器配置说你好世界。他拒绝了,并让我自己制作了一个简单的 php 页面,请注意,到目前为止,我在 PHP 编程方面的背景知识为零,所以在旁注中,我很高兴这是我的方式,但无论如何我都完成了任务。我有一个发送简单消息的页面,使用带有所需帐户的 smtp 服务器,使用 PHPMailer 库。 (见下方代码)

 <?php  


require_once 'C:\Webpage\PHPMailer-5.2-stable/PHPMailerAutoload.php';

$mail = new PHPMailer();
$mail->isSMTP();
$mail->SMTPAuth = true;
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->SMTPDebug   = 4; // 2 to enable SMTP debug information


$mail->Host = 'smtp.gmail.com';
$mail->Username = 'username@gmail.com';
$mail->Password = 'XXXXXXXXXXXXXXXXXXX';
$mail->SMTPSecure ='ssl';
$mail->Port = 465;

/*$mail->SMTPOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
        //'allow_self_signed' => true
    )
);*/

$mail->From = 'XXXXt@abc.com';
$mail->FromName = 'Example';
$mail->addReplyTo('testing@abc.com','Example');
$mail->AddAddress('user1@xyz.com', 'John Doe');


$mail->Subject = 'Hello World';
$mail->Body ='A test email!';
$mail->AltBody = 'A test email!';



 if(!$mail->Send()) {
    echo "Mailer Error: " . $mail->ErrorInfo;
 } else {
    echo "Message has been sent";
 }
        ?>

现在我知道这不是使用 PEAR,但从中我发现了一些我认为相关的有趣信息。该代码仅在

行时有效
 $mail->SMTPOptions = array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false,
            //'allow_self_signed' => true
        )
);

没有被注释掉它有效,但是当它被注释掉时,我收到一个关于此的错误。

Connection failed. Error #2: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed [C:\Webpage\PHPMailer-5.2-stable\class.smtp.php line 299]

所以我 googled 这个错误并导致 php.ini 文件更改 openssl.cafile 和 openssl.capath 值。我输入了下载 CA 证书并输入了正确的值路径,但它仍然无法正常工作。我把这些放在错误的地方了吗?或者有没有更简单的方法使用 PEAR 库来解决这个问题?请就此主题提供任何帮助!:)

更新(02/20/2018):

我已经下载了包并将路径设置到正确的位置,curl.cainfo ="C:\OpenSSL-Win64\bin\PEM\cacert.pem"openssl.cafile="C:\OpenSSL-Win64\bin\PEM\cacert.pem"。我仍然收到错误,我 运行 以下检查 ssl 位置以查看它是否正在使用 php.ini 文件并得到以下内容。

    <?php
 error_reporting(E_ALL);

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";
 }
$calocns=openssl_get_cert_locations();
//var_dump(openssl_get_cert_locations());


?>

结果:

    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 = f:\repo\winlibs_openssl_vc11_x86/cert.pem default_cert_file_env = SSL_CERT_FILE 
    default_cert_dir = f:\repo\winlibs_openssl_vc11_x86/certs 
    default_cert_dir_env = SSL_CERT_DIR 
    default_private_dir = f:\repo\winlibs_openssl_vc11_x86/private
 default_default_cert_area = f:\repo\winlibs_openssl_vc11_x86 
    ini_cafile = 
    ini_capath = 

我似乎做错了或需要知道如何更改位置,因为这些位置在我的计算机上不存在,而且我不明白当我更改路径时默认情况下如何转到这些位置配置文件本身。有什么想法吗?

显然还是证书问题。尝试使用 latest CA certificates extracted from Mozilla。只需下载它,将其放置在某个地方或替换您当前的 cacert.perm,将证书的路径添加到您的 php.ini 中的 openssl.cafilecurl.cainfo,然后重试。您现在可能想发表评论 openssl.capath

您可以阅读有关 issues related to CA certificate in PHPMailer Troubleshooting Wiki 的更多信息。


2018 年 2 月 20 日更新:

curl.cainfoopenssl.cafile 路径看起来不错,假设这是您下载的 cacert.pem 的正确路径。但是,当您 运行 openssl_get_cert_locations() 时,您的 ini_cafile 是空的。它应该反映您在 openssl.cafile 中设置的任何内容。在对 php.ini 进行更改后,您需要重新启动 Web 服务器 (Apache/nginx) 才能生效。重新启动后,通过 运行 宁 phpinfo() 检查 openssl.cafile 值,并确保它是正确的。

我不确定为什么默认的证书目录是这样的。也许以前安装过 Open SSL?无论哪种方式,它也是我的 non-existent 默认路径,但这并不重要,因为我的 ini_cafile 显示的值与我在 openssl.cafile 中定义的值相同。 openssl_get_cert_locations() 显示了它将查找证书的位置列表,因此如果其中有正确的位置,我认为应该没问题。