我最近将服务器从 Ubuntu 16.04 升级到 20.04,自升级以来,当我尝试通过 SMTP 发送邮件或尝试使用 PHP 7.0 连接到 S3 存储桶时收到以下错误。
stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14161044:SSL routines:state_machine:internal error
我尝试了 Stack Exchange 上的每一个解决方案,但运气不佳。我尝试将以下内容添加到我的 openssl.cnf 中:
openssl_conf = default_conf
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT:@SECLEVEL=1
然而这并没有帮助并且我仍然收到这些错误。
任何帮助将不胜感激。
答案1
从 php 5.5 迁移到 php 5.6 后,我在 PHPMailer 中遇到了这个问题。该问题与 openssl 使用的默认 TLS 版本有关。我不是 openssl 专家,但这是对我有用的解决方案。
我的 php 错误日志中记录的错误是
PHP Warning: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:\nerror:14161044:SSL routines:state_machine:internal error in /var/www/XXXXXX/XXXXXX/PHPMailer/class.smtp.php on line 319
class.smtp.php
PHPMailer 中第 319 行的代码使用了 crypto_type STREAM_CRYPTO_METHOD_TLS_CLIENT
,
if (! stream_socket_enable_crypto ( $this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT )) {
return false;
}
我将 crypto_type 从 更改STREAM_CRYPTO_METHOD_TLS_CLIENT
为STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
,请参阅 php 文档以了解可用的 crypto_typeshttps://www.php.net/manual/en/function.stream-socket-enable-crypto.php
if (! stream_socket_enable_crypto ( $this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT )) {
return false;
}
此更改帮我解决了错误。我不确定此问题是否是由于 OpenSSL 升级(OpenSSL 1.0.1f 到 OpenSSL 1.1.1f)或 PHP 升级(PHP 5.5.9 到 PHP 5.6.4)引起的
在找到此解决方案之前,我尝试了许多其他更改。因此,这些更改可能也对我的最终解决方案有所贡献。
- 我尝试在 PHPMailer 中设置以下内容,但没有奏效
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
)
);
- 另外,我向 openssl.cnf 添加了以下内容,但这也不起作用
openssl_conf = default_conf
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT:@SECLEVEL=1
答案2
@Swisstone 的答案包含修复程序(使用加密方法STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
),但它仅包含显式调用时的示例stream_socket_enable_crypto
。如果直接使用stream_socket_client
,则需要定义上下文并将其作为参数传递:
$contextOptions = array(
'ssl' => array(
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
),
);
$context = stream_context_create($contextOptions);
$sock = stream_socket_client($address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context);