ActionMailer SMTP“证书验证失败" [英] ActionMailer SMTP "certificate verify failed"

查看:114
本文介绍了ActionMailer SMTP“证书验证失败"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从我的 Rails 网络应用程序发送电子邮件,但我不想禁用 TLS 证书验证.但是由于某种原因,它总是失败并显示SSLv3 读取服务器证书 B:证书验证失败",即使服务器证书有效.

I want to send emails from my Rails web application, and I do not want to disable TLS certificate verification. However for some reason, it always fails with "SSLv3 read server certificate B: certificate verify failed", even though the server certificate is valid.

我用 openssl s_client(使用 /etc/ssl/certs/ca-certificates.crt)进行了双重检查,并且在 rails 控制台中运行以下内容也有效,成功交付.

I doubled checked with openssl s_client (using /etc/ssl/certs/ca-certificates.crt), and running the following in the rails console also works, delivering successfully.

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

The server has Rails 4.2.6 and 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 配置中的对等证书.

From the described behavior I am quite sure that peer verification has not been done in the console and that you need to explicitly set the certificate store for verifying peer certificates in your Rails configuration.

观察到它在控制台中运行但在 Rails 代码中不起作用是因为控制台代码中的 smtp.enable_tls不强制对等验证而您的 Rails 配置显然可以.实际上,当您将命令写入控制台时,您会打印出 SSLContext:

The observation that it works from the console but does not from Rails code is caused by the fact that smtp.enable_tls in your console code does not force peer verification whereas your Rails configuration apparently does. Indeed, when you write the command to the console, you get the SSLContext printed out:

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_modenil,因此默认情况下 SSLContext 上没有启用对等验证.

Note that @verify_mode is nil so there is no peer verification enabled by default on the SSLContext.

要在控制台中强制对等验证,以便您可以手动使用 SSL 设置,您需要使用自定义 SSLContext 并将其传递给 enable_tls:

To force peer verification in console, so that you can play with the SSL settings manually, you need to use a custom SSLContext and pass it to 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,并具有用于定义验证的证书存储.这是(除其他外)set_paramsSSLContext 中的 方法 确实如此.

Watch closely the differences: the SSLContext now has verify_mode set to 1 and has a certificate store for the verifications defined. This is (among other things) what the set_params method in SSLContext does.

现在,Rails 在为 SMTP 连接构建 SSLContext 时不会调用 set_params 方法.相反,它根据选项设置其上的各个属性(参见 这里此处 在源代码中).您已正确配置要验证对等证书的 Rails,但您尚未配置证书存储来验证对等证书.

Now, Rails does not call the set_params methods when constructing the SSLContext for SMTP connection. Instead, it sets the individual attributes on it according to the options (see here and here in the source code). You have properly configured Rails that you want to verify peer certificates but you have not configured a certificate store to verify peers against.

这可以使用 ca_fileca_path 选项 来完成,因此以下 Rails 配置应该适合您:

This can be done using the ca_file or ca_path options, so the following Rails configuration should work for you:

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 中没有正确记录指南...

这篇关于ActionMailer SMTP“证书验证失败"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆