我尝试使用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配置错误吗?
答案 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 options的stream_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