PHP 5.6 中的域验证问题与 PHPMailer 通过 TLS 发送邮件
Domain Verification in PHP 5.6 issue with PHPMailer for sending mails via TLS
我正在尝试使用带有 Let's Encrypt 证书的 PHPMailer 发送电子邮件,但在切换到 PHP 5.6 后,由于域验证失败,它无法正常工作。
Connection failed. Error #2: stream_socket_enable_crypto(): SSL operation >failed with code 1. OpenSSL Error messages:error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
明显的解决方法是禁用域验证,但我不愿意这样做,因为我想知道这是如何工作的
输出如下
php -r "var_dump(openssl_get_cert_locations());"
array(8) {
["default_cert_file"]=>
string(36) "/usr/local/apps/etc/openssl/cert.pem"
["default_cert_file_env"]=>
string(13) "SSL_CERT_FILE"
["default_cert_dir"]=>
string(33) "/usr/local/apps/etc/openssl/certs"
["default_cert_dir_env"]=>
string(12) "SSL_CERT_DIR"
["default_private_dir"]=>
string(35) "/usr/local/apps/etc/openssl/private"
["default_default_cert_area"]=>
string(27) "/usr/local/apps/etc/openssl"
["ini_cafile"]=>
string(0) ""
["ini_capath"]=>
string(0) ""
}
我在上述位置有 cert.pem,但我的证书和私钥存在于 /etc/ssl,我什至尝试为这些文件夹创建 Sysmlink,但验证仍然失败。
谁能解释一下验证是如何工作的,因为大多数解决方案都指向禁用域验证,即使经过几天的谷歌搜索后我也无法弄清楚。
我遗漏了一些东西,因为我拥有与证书相关的所有正确文件,并且它是有效的证书,因为我正在我的网站上使用它。
这是 PHPMailer
的代码
require 'PHPMailer-master/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 5;
$mail->Debugoutput = 'html';
$mail->Host = 'mydomin.com';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->SMTPAuth = true;
$mail->Username = "test@mydomain.com";
$mail->Password = "test";
$mail->setFrom('test@mydomain.com', 'Hii');
$mail->addAddress('test@gmail.com', 'John Doe');
$mail->Subject = 'PHPMailer GMail SMTP test';
$mail->msgHTML("<h2>Hello World</h2>");
$mail->AltBody = 'This is a plain-text message body';
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
)
);
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
您的服务器未在其响应中提供 letsencrypt X3 中间证书,仅提供叶证书。这还不够,因为大多数 CA 存储不包含 letsencrypt CA 证书,只包含它们签名的根证书,因此您需要中间件来桥接两者。从 here 获取中间证书并将其附加到您的证书文件。
以下是您如何从客户端查看它的工作情况:
$ wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
$ openssl s_client -CAfile lets-encrypt-x3-cross-signed.pem.txt -connect example.com:465
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = example.com
verify return:1
---
Certificate chain
0 s:/CN=example.com
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
...
Verify return code: 0 (ok)
如果您在服务器端捆绑该证书,它应该适用于所有没有本地中间证书的最新客户端。
我正在尝试使用带有 Let's Encrypt 证书的 PHPMailer 发送电子邮件,但在切换到 PHP 5.6 后,由于域验证失败,它无法正常工作。
Connection failed. Error #2: stream_socket_enable_crypto(): SSL operation >failed with code 1. OpenSSL Error messages:error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
明显的解决方法是禁用域验证,但我不愿意这样做,因为我想知道这是如何工作的
输出如下
php -r "var_dump(openssl_get_cert_locations());"
array(8) {
["default_cert_file"]=>
string(36) "/usr/local/apps/etc/openssl/cert.pem"
["default_cert_file_env"]=>
string(13) "SSL_CERT_FILE"
["default_cert_dir"]=>
string(33) "/usr/local/apps/etc/openssl/certs"
["default_cert_dir_env"]=>
string(12) "SSL_CERT_DIR"
["default_private_dir"]=>
string(35) "/usr/local/apps/etc/openssl/private"
["default_default_cert_area"]=>
string(27) "/usr/local/apps/etc/openssl"
["ini_cafile"]=>
string(0) ""
["ini_capath"]=>
string(0) ""
}
我在上述位置有 cert.pem,但我的证书和私钥存在于 /etc/ssl,我什至尝试为这些文件夹创建 Sysmlink,但验证仍然失败。
谁能解释一下验证是如何工作的,因为大多数解决方案都指向禁用域验证,即使经过几天的谷歌搜索后我也无法弄清楚。
我遗漏了一些东西,因为我拥有与证书相关的所有正确文件,并且它是有效的证书,因为我正在我的网站上使用它。
这是 PHPMailer
的代码require 'PHPMailer-master/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 5;
$mail->Debugoutput = 'html';
$mail->Host = 'mydomin.com';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->SMTPAuth = true;
$mail->Username = "test@mydomain.com";
$mail->Password = "test";
$mail->setFrom('test@mydomain.com', 'Hii');
$mail->addAddress('test@gmail.com', 'John Doe');
$mail->Subject = 'PHPMailer GMail SMTP test';
$mail->msgHTML("<h2>Hello World</h2>");
$mail->AltBody = 'This is a plain-text message body';
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
)
);
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
您的服务器未在其响应中提供 letsencrypt X3 中间证书,仅提供叶证书。这还不够,因为大多数 CA 存储不包含 letsencrypt CA 证书,只包含它们签名的根证书,因此您需要中间件来桥接两者。从 here 获取中间证书并将其附加到您的证书文件。
以下是您如何从客户端查看它的工作情况:
$ wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
$ openssl s_client -CAfile lets-encrypt-x3-cross-signed.pem.txt -connect example.com:465
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = example.com
verify return:1
---
Certificate chain
0 s:/CN=example.com
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
...
Verify return code: 0 (ok)
如果您在服务器端捆绑该证书,它应该适用于所有没有本地中间证书的最新客户端。