PHP - 使用 STARTTLS 和自签名证书的 Swiftmailer
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26896265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP - Swiftmailer using STARTTLS and self signed certificates
提问by David Ventura
I'm trying to send an email with php and swiftmailer, using STARTTLS, but I'm getting a certificate error. I have root access to the SMTP server, and the certificate used is self-signed. I'm using Debian on both machines (web server and smtp server)
我正在尝试使用 STARTTLS 使用 php 和 swiftmailer 发送电子邮件,但出现证书错误。我有 SMTP 服务器的 root 访问权限,并且使用的证书是自签名的。我在两台机器上都使用 Debian(网络服务器和 smtp 服务器)
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
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
Do I need to add my own certificate somewhere to get it accepted? Or is this some OpenSSL configuration error?
我是否需要在某处添加我自己的证书才能被接受?或者这是一些 OpenSSL 配置错误?
回答by Dave Kennard
Swiftmailer has now been updated to include an option for this. It can now be solved using the setStreamOptions
method from your Swift_SmtpTransport
instance rather than editing the swift class.
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)));
回答by PiTheNumber
I got the same problem using Swiftmailer in Laravel.
我在 Laravel 中使用 Swiftmailer 遇到了同样的问题。
Looks like there is no option for this in Swiftmailer. Clean solution would be to add your own root CAto your server and sign your mail server certificate with this CA. The certificate would be valid after this. See for example this tutorial.
Swiftmailer 中似乎没有此选项。干净的解决方案是将您自己的根 CA添加到您的服务器并使用此 CA 签署您的邮件服务器证书。此后证书将有效。例如,请参阅本教程。
Anyway, a quick dirty hack you should not use would be to edit swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php
. In _establishSocketConnection()
line 253 replace:
无论如何,你不应该使用的一个快速肮脏的黑客是编辑swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php
. 在_establishSocketConnection()
第 253 行替换:
$options = array();
with something like this:
像这样:
$options = array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false));
This will change the ssl optionsof stream_context_create()(a few lines below $options
):
这将改变SSL选项的stream_context_create)( (几行如下$options
):
$this->_stream = @stream_socket_client($host.':'.$this->_params['port'], $errno,
$errstr, $timeout, STREAM_CLIENT_CONNECT, stream_context_create($options));
回答by Alex
You do not need to edit /vendor
files. You can specify (undocumented) options in your config/mail.php
file:
您不需要编辑/vendor
文件。您可以在config/mail.php
文件中指定(未记录的)选项:
'stream' => [
'ssl' => [
'allow_self_signed' => true,
'verify_peer' => false,
'verify_peer_name' => false,
],
],
You can check it yourself in vendor/laravel/framework/src/Illuminate/Mail/TransportManager.php
on line ~50:
您可以vendor/laravel/framework/src/Illuminate/Mail/TransportManager.php
在第 50 行自行检查:
...
if (isset($config['stream'])) {
$transport->setStreamOptions($config['stream']);
}
...
回答by Tudor
For me, I had to add $transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false, 'verify_peer_name' => false)));
to the Mailer.php file, see:
对我来说,我必须添加$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;
}
I got this from another link, can't find it now.
我从另一个链接上得到的,现在找不到了。
One think that I did extra to the other answers was to specify the 'verify_peer_name' => false
有人认为我对其他答案做了额外的说明是指定 'verify_peer_name' => false