ActionMailer SMTP "certificate verify failed"
ActionMailer SMTP "certificate verify failed"
我想从我的 Rails 网络应用程序发送电子邮件,我不想禁用 TLS 证书验证。但是由于某种原因,即使服务器证书有效,它总是失败并显示 "SSLv3 read server certificate B: certificate verify failed"。
我用 openssl s_client
(使用 /etc/ssl/certs/ca-certificates.crt
)进行了双重检查,运行 rails 控制台中的以下内容也有效,交付成功。
smtp = Net::SMTP.new(host, port)
smtp.enable_tls
smtp.start("localhost", username, password, :login) do |smtp|
smtp.send_message msgstr, from, to
end
服务器有 Rails 4.2.6 和 Ruby 2.3.0
config.action_mailer.smtp_setting = {
address:
port: 465,
user_name:
password:
authentication: :login,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
enable_starttls_auto: false,
ssl: true
}
根据所描述的行为,我非常确定尚未在控制台中完成对等验证,并且您需要在 Rails 配置中显式 设置用于验证对等证书的证书存储区.
为什么它 "works" 在控制台中以及如何在那里实际验证对等点:
观察到它在控制台中有效但在 Rails 代码中无效是因为 smtp.enable_tls
在您的控制台代码中 不强制进行对等验证 而你的 Rails 配置显然是。实际上,当您将命令写入控制台时,您会打印出 SSLContext
:
smtp.enable_tls
# => #<OpenSSL::SSL::SSLContext:0x000000064043d0 @cert=nil, @key=nil,
@client_ca=nil, @ca_file=nil, @ca_path=nil, @timeout=nil,
@verify_mode=nil, @verify_depth=nil, @renegotiation_cb=nil,
@verify_callback=nil, @cert_store=nil, @extra_chain_cert=nil,
@client_cert_cb=nil, @session_id_context=nil, @tmp_dh_callback=nil,
@session_get_cb=nil, @session_new_cb=nil, @session_remove_cb=nil,
@tmp_ecdh_callback=nil, @servername_cb=nil, @npn_protocols=nil,
@alpn_protocols=nil, @alpn_select_cb=nil, @npn_select_cb=nil>
请注意 @verify_mode
是 nil
,因此在 SSLContext
上默认不启用对等验证。
要在控制台中强制进行对等验证,以便您可以手动使用 SSL 设置,您需要使用自定义 SSLContext
并将其传递给 enable_tls
:
ssl_context = Net::SMTP.default_ssl_context
ssl_context.set_params
smtp.enable_tls(ssl_context)
# => #<OpenSSL::SSL::SSLContext:0x000000063c27c8 @cert=nil, @key=nil,
@client_ca=nil, @ca_file=nil, @ca_path=nil, @timeout=nil,
@verify_mode=1, @verify_depth=nil, @renegotiation_cb=nil,
@verify_callback=nil, @cert_store=#<OpenSSL::X509::Store:0x00000002894408 @verify_callback=nil, @error=nil, @error_string=nil, @chain=nil, @time=nil>, @extra_chain_cert=nil,
@client_cert_cb=nil, @session_id_context=nil, @tmp_dh_callback=nil,
@session_get_cb=nil, @session_new_cb=nil, @session_remove_cb=nil,
@tmp_ecdh_callback=nil, @servername_cb=nil, @npn_protocols=nil,
@alpn_protocols=nil, @alpn_select_cb=nil, @npn_select_cb=nil>
仔细观察差异:SSLContext
现在已将 verify_mode
设置为 1 并具有用于定义验证的证书存储。这就是 SSLContext
中的 set_params
method 所做的(除其他事项外)。
如何在 Rails
中配置证书存储
现在,Rails 在为 SMTP 连接构建 SSLContext
时不会调用 set_params
方法。相反,它根据选项设置其上的各个属性(请参阅源代码中的 here and here)。您已正确配置 Rails 要验证对等证书,但 您尚未配置证书存储以根据 验证对等证书。
这可以使用 ca_file
或 ca_path
选项 完成,因此以下 Rails 配置应该适合您:
config.action_mailer.smtp_setting = {
...
ssl: true
enable_starttls_auto: false,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}
我不知道为什么 Rails Guides...
中没有正确记录
这个 Rails 配置对我有用(使用 Ruby 2.2.2 和 Rails 5):
ActionMailer::Base.smtp_setting = {
...
enable_starttls_auto: true,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
openssl_verify_depth: 3, # if your CA is a sub signer
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}
我想从我的 Rails 网络应用程序发送电子邮件,我不想禁用 TLS 证书验证。但是由于某种原因,即使服务器证书有效,它总是失败并显示 "SSLv3 read server certificate B: certificate verify failed"。
我用 openssl s_client
(使用 /etc/ssl/certs/ca-certificates.crt
)进行了双重检查,运行 rails 控制台中的以下内容也有效,交付成功。
smtp = Net::SMTP.new(host, port)
smtp.enable_tls
smtp.start("localhost", username, password, :login) do |smtp|
smtp.send_message msgstr, from, to
end
服务器有 Rails 4.2.6 和 Ruby 2.3.0
config.action_mailer.smtp_setting = {
address:
port: 465,
user_name:
password:
authentication: :login,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
enable_starttls_auto: false,
ssl: true
}
根据所描述的行为,我非常确定尚未在控制台中完成对等验证,并且您需要在 Rails 配置中显式 设置用于验证对等证书的证书存储区.
为什么它 "works" 在控制台中以及如何在那里实际验证对等点:
观察到它在控制台中有效但在 Rails 代码中无效是因为 smtp.enable_tls
在您的控制台代码中 不强制进行对等验证 而你的 Rails 配置显然是。实际上,当您将命令写入控制台时,您会打印出 SSLContext
:
smtp.enable_tls
# => #<OpenSSL::SSL::SSLContext:0x000000064043d0 @cert=nil, @key=nil,
@client_ca=nil, @ca_file=nil, @ca_path=nil, @timeout=nil,
@verify_mode=nil, @verify_depth=nil, @renegotiation_cb=nil,
@verify_callback=nil, @cert_store=nil, @extra_chain_cert=nil,
@client_cert_cb=nil, @session_id_context=nil, @tmp_dh_callback=nil,
@session_get_cb=nil, @session_new_cb=nil, @session_remove_cb=nil,
@tmp_ecdh_callback=nil, @servername_cb=nil, @npn_protocols=nil,
@alpn_protocols=nil, @alpn_select_cb=nil, @npn_select_cb=nil>
请注意 @verify_mode
是 nil
,因此在 SSLContext
上默认不启用对等验证。
要在控制台中强制进行对等验证,以便您可以手动使用 SSL 设置,您需要使用自定义 SSLContext
并将其传递给 enable_tls
:
ssl_context = Net::SMTP.default_ssl_context
ssl_context.set_params
smtp.enable_tls(ssl_context)
# => #<OpenSSL::SSL::SSLContext:0x000000063c27c8 @cert=nil, @key=nil,
@client_ca=nil, @ca_file=nil, @ca_path=nil, @timeout=nil,
@verify_mode=1, @verify_depth=nil, @renegotiation_cb=nil,
@verify_callback=nil, @cert_store=#<OpenSSL::X509::Store:0x00000002894408 @verify_callback=nil, @error=nil, @error_string=nil, @chain=nil, @time=nil>, @extra_chain_cert=nil,
@client_cert_cb=nil, @session_id_context=nil, @tmp_dh_callback=nil,
@session_get_cb=nil, @session_new_cb=nil, @session_remove_cb=nil,
@tmp_ecdh_callback=nil, @servername_cb=nil, @npn_protocols=nil,
@alpn_protocols=nil, @alpn_select_cb=nil, @npn_select_cb=nil>
仔细观察差异:SSLContext
现在已将 verify_mode
设置为 1 并具有用于定义验证的证书存储。这就是 SSLContext
中的 set_params
method 所做的(除其他事项外)。
如何在 Rails
中配置证书存储现在,Rails 在为 SMTP 连接构建 SSLContext
时不会调用 set_params
方法。相反,它根据选项设置其上的各个属性(请参阅源代码中的 here and here)。您已正确配置 Rails 要验证对等证书,但 您尚未配置证书存储以根据 验证对等证书。
这可以使用 ca_file
或 ca_path
选项 完成,因此以下 Rails 配置应该适合您:
config.action_mailer.smtp_setting = {
...
ssl: true
enable_starttls_auto: false,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}
我不知道为什么 Rails Guides...
中没有正确记录这个 Rails 配置对我有用(使用 Ruby 2.2.2 和 Rails 5):
ActionMailer::Base.smtp_setting = {
...
enable_starttls_auto: true,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
openssl_verify_depth: 3, # if your CA is a sub signer
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}