PHP - 使用STARTTLS和自签名证书的Swiftmailer

时间:2014-11-12 20:48:29

标签: php smtp certificate swiftmailer self-signed

我尝试使用STARTTLS发送带有php和swiftmailer的电子邮件,但我收到了证书错误。我具有SMTP服务器的root访问权限,并且使用的证书是自签名的。 我在两台机器(Web服务器和smtp服务器)上使用Debian

PHP message: PHP Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in [..]/lib/classes/Swift/Transport/StreamBuffer.php on line 97 PHP message: PHP Fatal error: Uncaught exception 'Swift_TransportException' with message 'Unable to connect with TLS encryption' in [..]/lib/classes/Swift/Transport/EsmtpTransport.php:294

我是否需要在某处添加自己的证书才能接受?或者这是一些OpenSSL配置错误吗?

4 个答案:

答案 0 :(得分:14)

Swiftmailer现已更新,其中包含一个选项。现在可以使用setStreamOptions实例中的Swift_SmtpTransport方法解决它,而不是编辑swift类。

$transport = Swift_SmtpTransport::newInstance('smtp.server.com', 123, 'tls')
    ->setUsername('username')
    ->setPassword('password')
    ->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false)));

答案 1 :(得分:13)

我在Laravel中使用Swiftmailer遇到了同样的问题。

看起来在Swiftmailer中没有这个选项。干净的解决方案是将您自己的root CA添加到您的服务器,并使用此CA签署您的邮件服务器证书。证书在此之后有效。请参阅示例this tutorial

无论如何,你不应该使用的快速肮脏黑客就是编辑swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php。在_establishSocketConnection()第253行替换:

$options = array();

有这样的事情:

$options = array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false));

这会更改ssl optionsstream_context_create()$options以下几行):

$this->_stream = @stream_socket_client($host.':'.$this->_params['port'], $errno, 
    $errstr, $timeout, STREAM_CLIENT_CONNECT, stream_context_create($options));

答案 2 :(得分:5)

您无需编辑/vendor个文件。您可以在config/mail.php文件中指定(未记录的)选项:

'stream' => [
    'ssl' => [
        'allow_self_signed' => true,
        'verify_peer' => false,
        'verify_peer_name' => false,
    ],
],

您可以在vendor/laravel/framework/src/Illuminate/Mail/TransportManager.php在线~50:

自行查看
...
if (isset($config['stream'])) {
    $transport->setStreamOptions($config['stream']);
}
...

答案 3 :(得分:0)

对我来说,我必须将$transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false)));添加到Mailer.php文件中,请参阅:

    /**
     * Returns the SMTP transport
     *
     * @return \Swift_SmtpTransport
     */
    protected function getSmtpInstance(): \Swift_SmtpTransport {
            $transport = new \Swift_SmtpTransport();
            $transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
            $transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1'));
            $transport->setPort($this->config->getSystemValue('mail_smtpport', 25));
            if ($this->config->getSystemValue('mail_smtpauth', false)) {
                    $transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
                    $transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
                    $transport->setAuthMode($this->config->getSystemValue('mail_smtpauthtype', 'LOGIN'));
            }
            $smtpSecurity = $this->config->getSystemValue('mail_smtpsecure', '');
            if (!empty($smtpSecurity)) {
                    $transport->setEncryption($smtpSecurity);
            }
            $streamingOptions = $this->config->getSystemValue('mail_smtpstreamoptions', []);
            if (is_array($streamingOptions) && !empty($streamingOptions)) {
                    $transport->setStreamOptions($streamingOptions);
            }

            /* EDIT - allow self-signed mail cert */
            $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false)));
            /* EDIT end */

            return $transport;
    }

我是从另一个链接获得的,现在找不到。

有人认为我对其他答案还有其他要求,那就是指定'verify_peer_name' => false