【问题标题】:Zend Framework cannot open ssl socket (Abstract.php)Zend 框架无法打开 ssl 套接字 (Abstract.php)
【发布时间】:2017-11-16 19:04:56
【问题描述】:

我正在配置 Magento 1.9.1 以使用外部 SMTP 发送电子邮件,使用 SMTP PRO (https://www.magentocommerce.com/magento-connect/smtp-pro-email-free-custom-smtp-email.html)。

我已经设置了配置(主机名、端口、用户名、密码),但是当我尝试发送测试电子邮件时,它失败并显示“无法打开套接字”错误消息。如果我深入研究代码,我发现错误是从 lib/Zend/Mail/Protocol/Abstract.php 中的这段代码生成的:

$this->_socket = @stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);

        if ($this->_socket === false) {
            if ($errorNum == 0) {
                $errorStr = $remote.' Could not open socket '.phpversion();
            }
            /**
             * @see Zend_Mail_Protocol_Exception
             */
            #require_once 'Zend/Mail/Protocol/Exception.php';
            throw new Zend_Mail_Protocol_Exception($errorStr);
        }

我的 PHP 环境 (5.6.30) 支持 openssl(见下图和 sn-p)

[root@ns3023903 httpdocs]# php -r 'print_r(stream_get_transports());'
Array
(
    [0] => tcp
    [1] => udp
    [2] => unix
    [3] => udg
    [4] => ssl
    [5] => sslv3
    [6] => sslv2
    [7] => tls
)

没有防火墙问题,因为我既可以在端口 465 上 telnet 到目标主机,也可以使用 phpmailer 使用相同的 SMTP 发送电子邮件,并使用我用来运行站点虚拟主机的同一用户。

我在 CentOS 7 64 位服务器上,禁用了 SELinux,如果这很重要,我正在使用 Plesk 12 配置虚拟主机。

名称解析也可以正常工作(我可以正确 ping SMTP 名称并且可以正常查找 IP 地址)。

我显然在这里遗漏了一些东西......但是什么?

【问题讨论】:

    标签: php email magento ssl zend-framework


    【解决方案1】:

    事实证明,根据 stream_socket_client() 假定的默认选项,PHP 版本 5.6.30 发生了一些变化。

    首先,在摆脱 Magento 核心代码中 stream_socket_client 调用前面的愚蠢 @ 之前,我实际上无法理解发生了什么。我什至没有接近 PHP 开发人员,所以我一直忘记那个愚蠢的 @ 前缀是干什么用的(老实说,我什至不知道它为什么存在)。

    删除@后我看到了这个:

    Warning: stream_socket_client(): Peer certificate CN=`*.aruba.it' did not match expected CN=`mail.myclientreserveddomain.com'
    

    我查看了一些 PHP 文档,并得出了与核心代码的两行差异(我知道这不对,我现在将对其进行重构,但我想先分享一下快速解决方法)。

    基本上我正在创建一个上下文并使用另一个版本的 stream_socket_client 调用

     $context = stream_context_create(['ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
        ]]);
    // open connection
    $this->_socket = stream_socket_client($remote, $errorNum, $errorStr, 120, STREAM_CLIENT_CONNECT, $context); 
    

    跳过对等点名称验证是关键。不知道为什么/如何/何时从 php pre 5.6.30 更改为 PHP 5.6.30(我说过我不是 PHP 开发人员吗?)但它有效。我还尝试在 PHP 5.4.x 下运行原始代码,但它在没有解决方法的情况下工作,所以肯定是这样。

    【讨论】:

      猜你喜欢
      • 2016-03-23
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      相关资源
      最近更新 更多