jruby-openssl
jruby-openssl copied to clipboard
Net::SMTP behaves differently in JRuby than in MRI
Sometime after jruby-1.7.19
a change was introduced that changes the Net::SMTP
behavior with respect with MRI.
Repro:
require "net/smtp"
message = <<-END_OF_MESSAGE
From: Your Name <[email protected]>
To: Destination Address <[email protected]>
Subject: test message
Date: Sat, 23 Jun 2001 16:26:43 +0900
Message-Id: <[email protected]>
This is a test message.
END_OF_MESSAGE
smtp = Net::SMTP.new("smtp.somewhere.com", 25)
# This is weird, since we are not using TLS but done by default in the "mail" gem
# In any case, in MRI it doesn't cause any issue.
smtp.enable_starttls_auto
smtp.start("localhost") do |smtp_obj|
response = smtp_obj.send_message(message, "[email protected]", "[email protected]")
end
In jruby-1.7.22
and jruby-9.0.1.0
I get a Java stack-trace:
$ ruby repro.rb
Handshaker.java:1429:in `checkThrown': java.lang.RuntimeException: Algorithm NONE not available
from SSLEngineImpl.java:535:in `checkTaskThrown'
from SSLEngineImpl.java:813:in `readNetRecord'
from SSLEngineImpl.java:781:in `unwrap'
from SSLEngine.java:624:in `unwrap'
from SSLSocket.java:605:in `readAndUnwrap'
from SSLSocket.java:483:in `doHandshake'
from SSLSocket.java:233:in `connectImpl'
from SSLSocket.java:210:in `connect'
I can confirm that in jruby-1.7.19
and MRI (2.2.3
) the mail message is sent as expected.
I think it's a little weird that the mail
gem call enable_starttls_auto
by default, unless explicitly told not to (https://github.com/mikel/mail/blob/master/lib/mail/network/delivery_methods/smtp.rb), but in any case, I believe the difference in behavior of the current JRuby release and MRI is worth addressing.
Please do let me know if more information is needed.
Thanks.
I can confirm we hit the same thing after upgrading to jruby-1.7.22. In our case, the SMTP server was also over port 25, but should be supporting STARTTLS (it's Mandrill's SMTP server if that helps).
As one other data point, we were actually getting a slightly different error messages in our default jruby-1.7.22 installation originally:
OpenSSL::SSL::SSLError: RSA ServerKeyExchange does not comply to algorithm constraints
from org/jruby/ext/openssl/SSLSocket.java:210:in `connect'
from /opt/rbenv/versions/jruby-1.7.22/lib/ruby/1.9/net/smtp.rb:584:in `tlsconnect'
from /opt/rbenv/versions/jruby-1.7.22/lib/ruby/1.9/net/smtp.rb:561:in `do_start'
from /opt/rbenv/versions/jruby-1.7.22/lib/ruby/1.9/net/smtp.rb:520:in `start'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/network/delivery_methods/smtp.rb:112:in `deliver!'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:2141:in `do_delivery'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:236:in `deliver'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/actionmailer-4.0.13/lib/action_mailer/base.rb:456:in `deliver_mail'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/activesupport-4.0.13/lib/active_support/notifications.rb:159:in `instrument'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/activesupport-4.0.13/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/activesupport-4.0.13/lib/active_support/notifications.rb:159:in `instrument'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/actionmailer-4.0.13/lib/action_mailer/base.rb:454:in `deliver_mail'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:236:in `deliver'
from (irb):3:in `evaluate'
from org/jruby/RubyKernel.java:1079:in `eval'
from org/jruby/RubyKernel.java:1479:in `loop'
from org/jruby/RubyKernel.java:1242:in `catch'
from org/jruby/RubyKernel.java:1242:in `catch'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/railties-4.0.13/lib/rails/commands/console.rb:90:in `start'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/railties-4.0.13/lib/rails/commands/console.rb:9:in `start'
from /srv/data/apps/shared/vendor/bundle/jruby/1.9/gems/railties-4.0.13/lib/rails/commands.rb:62:in `(root)'
from org/jruby/RubyKernel.java:1040:in `require'
However, after adding the latest jruby-openssl
v0.9.12 gem to our Gemfile, then we started getting this same Algorithm NONE not available
error instead.
We are seeing the same Algorithm NONE not available
error in our application using jruby v.1.7.22 (and not v.1.7.19), even without starttls.
I cannot reproduce using jruby-1.7.22. What version of Java are you using?
For me it's java version "1.7.0_85": OpenJDK Runtime Environment (IcedTea 2.6.1) (7u85-2.6.1-6~deb7u1) OpenJDK 64-Bit Server VM (build 24.85-b03, mixed mode)
The original report was using Oracle's java 8:
$ java -version
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
It seems to me that this is a failure to negotiate SSL handshake with the server in question.
[1] pry(main)> RUBY_DESCRIPTION
=> "jruby 9.0.4.0 (2.2.2) 2015-11-12 b9fb7aa Java HotSpot(TM) 64-Bit Server VM 25.40-b25 on 1.8.0_40-b25 +jit [darwin-x86_64]"
[2] pry(main)> require 'net/smtp'
=> true
[3] pry(main)> smtp = Net::SMTP.new('smtp.mandrillapp.com', 587)
=> #<Net::SMTP smtp.mandrillapp.com:587 started=false>
[4] pry(main)> smtp.enable_starttls_auto
=> #<OpenSSL::SSL::SSLContext:0x65c86db8>
[5] pry(main)> smtp.start
Java::JavaLang::RuntimeException: Algorithm NONE not available
from sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1419)
[6] pry(main)> smtp = Net::SMTP.new('smtp.gmail.com', 587)
=> #<Net::SMTP smtp.gmail.com:587 started=false>
[7] pry(main)> smtp.enable_starttls_auto
=> #<OpenSSL::SSL::SSLContext:0x66273da0>
[8] pry(main)> smtp.start
=> #<Net::SMTP smtp.gmail.com:587 started=true>
In the above, you see that the negotiation fails with our SMTP service provider, but the same procedure works with Gmail. It is not clear to me what ciphers are tried and what ciphers problematic ones support, but whatever Gmail is using, JRuby 9k can use. (This happens with both 0.9.11 and 0.9.12 jruby-openssl gem.)
I was debugging with -J-Djavax.net.debug=ssl option.
- Gmail ; cipher is TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- Mandrill ; cipher is SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
My Env
jruby 1.7.22 (1.9.3p551) 2015-08-20 c28f492 on Java HotSpot(TM) 64-Bit Server VM 1.8.0_66-b17 +jit [darwin-x86_64]
I've done some digging as well, and it turns out (no real surprise) that TLS is attempted in my case as well and that the cipher suite for my local postfix is the same as Mandrill's. My bet is that DES 40 is simply not supported anymore.
Since I am also having the same issue and the culprit is mandrill, has anyone been able to fix this yet?
I tried changing my port to 465
and now have this:
2015-11-26T00:31:19.379Z 28509 TID-afw WARN: org/jruby/ext/socket/RubyTCPSocket.java:111:in `initialize'
org/jruby/RubyIO.java:1179:in `open'
/home/func01admin/.rbenv/versions/jruby-1.7.23/lib/ruby/1.9/net/smtp.rb:541:in `tcp_socket'
/home/func01admin/.rbenv/versions/jruby-1.7.23/lib/ruby/1.9/net/smtp.rb:550:in `do_start'
org/jruby/ext/timeout/Timeout.java:115:in `timeout'
/home/func01admin/.rbenv/versions/jruby-1.7.23/lib/ruby/1.9/net/smtp.rb:550:in `do_start'
/home/func01admin/.rbenv/versions/jruby-1.7.23/lib/ruby/1.9/net/smtp.rb:520:in `start'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/network/delivery_methods/smtp.rb:112:in `deliver!'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:2141:in `do_delivery'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:236:in `deliver'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/actionmailer-4.1.14/lib/action_mailer/base.rb:527:in `deliver_mail'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `instrument'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/activesupport-4.1.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `instrument'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/actionmailer-4.1.14/lib/action_mailer/base.rb:525:in `deliver_mail'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/mail-2.6.3/lib/mail/message.rb:236:in `deliver'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq_mailer-0.0.8/lib/sidekiq_mailer/proxy.rb:24:in `deliver!'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq_mailer-0.0.8/lib/sidekiq_mailer/worker.rb:5:in `perform'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:75:in `execute_job'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:52:in `process'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:127:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/newrelic_rpm-3.11.1.284/lib/new_relic/agent/instrumentation/sidekiq.rb:33:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/newrelic_rpm-3.11.1.284/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:353:in `perform_action_with_newrelic_trace'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/newrelic_rpm-3.11.1.284/lib/new_relic/agent/instrumentation/sidekiq.rb:29:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:15:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/logging.rb:30:in `with_context'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:11:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `invoke'
org/jruby/RubyProc.java:281:in `call'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:51:in `process'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:98:in `stats'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:50:in `process'
org/jruby/RubyKernel.java:1930:in `public_send'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `invoke'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `task'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `task'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `initialize'
/srv/www/reppro/shared/bundle/jruby/1.9/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `create'
Workaround:
using smtp.enable_starttls_auto OpenSSL::SSL::SSLContext.new("TLSv1_2_client")
.
@TheKidCoder : I had the same issue after changing the port to 465, It's because you need to start Postfix on your mac and also enable port 465, which is disabled by default:
- First edit the master.conf:
sudo vim /etc/postfix/master.cf
- Remove the '#' comment from line
465 inet n - n - - smtpd
- now start postfix, or reload it:
sudo postfix reload
orsudo postfix start
To follow up on @k77ch7 's workaround, the following monkey patch works for me:
require 'net/smtp'
class << Net::SMTP
remove_method :default_ssl_context # if defined?(Net::SMTP.default_ssl_context)
end
module Net
class SMTP
def SMTP.default_ssl_context
OpenSSL::SSL::SSLContext.new('TLSv1_2_client')
end
end
end
This will globally change SMTP to use a TLS v1.2 cipher suite, which avoids this issue.
I encountered this error when using Rails with Postfix configured as a gmail relay on Ubuntu.
The solution was to ensure that the default "TLS Parameters" are commented out or removed from /etc/postfix/main.cf after configuring the relay settings. Restart postfix after modifications to main.cf
@maccharlesnmx Did you have this issue on a recent version of JRuby? The most recent replies here were all (somewhat older) versions of JRuby 1.7.
@headius I'm using JRuby 9.1.12.0
To be clear, I was able to resolve the "Algorithm NONE not available" error by adjusting my Postfix configuration and no monkey patching. I posted my case here because it seemed like a very specific error message, and searching for it leads directly to this issue, so it might help others.
I can't be certain that my case is the same as the original setup from @ylansegal, but it seems related to those who mention using JRuby with Postfix.
I'm pretty sure this is really an OpenSSL bug so I'm transferring the issue there.
Perhaps someone can test against a more recent JRuby? We expanded support for ciphers since this bug was last updated.