ActionMailer SMTP certificate verify failed
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.
Why it "works" in the console and how to actually verify peers there:
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>
Note that @verify_mode
is nil
so there is no peer verification enabled by default on the SSLContext
.
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>
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.
How to configure the certificate store in 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.
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",
...
}
I have no idea why this is not properly documented in the Rails Guides...
Why isn't a self signed SMTP Certificate ignored by Rails ActionMailer 6.1 / Ruby 3.0?
This boils down to the following: When I use the settings
enable_starttls_auto: false,
openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE
it does perform TLS transmission and fails with state=error: certificate verify failed (self signed certificate) (OpenSSL::SSL::SSLError)
, which is double wrong in my eyes, as it should never even start a TLS handshake and if so, should skip certificate validation.
Rails uses the Mail-Gem to handle these options, which indeed had an incompatible change.
As a workaround in my case, removing the enable_starttls_auto
setting completely (thus keeping TLS transmission), only disabling the certificate validation with openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE
was helping (but will not help if you have other reasons to avoid TLS than having a bogus certificate).
Rails Action Mailer TLS Certificate Issues
Resolved issue by using sendmail and configuring sendmail to use the proper smtp settings required to use rackspace email hosting.
ssl erros sending mail using devise in rails 6
The problem
If you encounter this problem when running Ruby on Rails:
OpenSSL::SSL::SSLError (hostname "localhost" does not match the server certificate)
it is likely due to ActionMailer using the smtp as the delivery_method and your local mail server supporting TLS/SSL, but not having a correct/valid certificate.
The solution
You can add a valid certificate, but if the server is just used for sending out mails, this may not be suited. In that case, you can change the delivery_method to sendmail, which makes ActionMailer use the sendmail binary directly.
source
ActionMailer: Using multiple self-signed certificates
1) Is it possible to set more than one ,in my case three, different self-signed certificates? If the answer is yes, how?
The ca_file
can contain multiple CA certificates in PEM format. Just put them one after each other into the file, i.e. cat cert1.pem cert2.pem > ca.pem
. Make sure that each of the input files has a line end at the end though.
2) Is it possible to use a .der file as a self-signed certificate instead of a .crt file? or Should I always convert a .der file into a .crt file when I use it as a self-signed certificate?
DER and PEM are both essentially the same data only with a different encoding (binary vs. base64 with some ASCII envelope) and it is easy to convert one into the other. ca_file
expects a list of PEM, not DER.
Related Topics
How to Get Repeated Elements from Ruby Array
How to 'Join' an Array Adding to the Beginning of the Resulting String the First Character to Join
How to Split a String of Repeated Characters with Uneven Amounts? Ruby
What Happened When Pass a Method to Iterator Method
Copy One Slide from Google Slides into a New Presentation Using API
Convert Spreadsheet Column Index into Character Sequence
How to Fill Out Login Form with Mechanize in Ruby
What Is the Fastest Way to Sort a Hash
Trying to Find Vowels of a String Using Ruby While Loops
Different Behaviour of 'Do .. End' and "{..}" Block in Ruby
Override a Method Inside a Gem from Another Gem
Symbol#To_Proc Shorthand with the Stabby Lambda Syntax
Calling a Method of a Ruby Singleton Without the Reference of 'Instance'
What Is the Directory Structure for Adding Sorbet Rbis to a Gem