From db2b32933162ef6098d9249750283c6003c765ff Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 6 Nov 2016 16:45:38 +0100 Subject: [PATCH] Fixed issue#240 - TLS/SSL for SMTP with exchange. Improved Net::SMTP.do_start to auto detect available auth types based on SMTP server capabilities. --- app/models/channel/driver/smtp.rb | 8 ++++- lib/core_ext/net/smtp.rb | 52 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 lib/core_ext/net/smtp.rb diff --git a/app/models/channel/driver/smtp.rb b/app/models/channel/driver/smtp.rb index 3da36e565..a48918dd8 100644 --- a/app/models/channel/driver/smtp.rb +++ b/app/models/channel/driver/smtp.rb @@ -10,8 +10,10 @@ class Channel::Driver::Smtp host: 'some.host', port: 25, enable_starttls_auto: true, # optional + openssl_verify_mode: 'none', # optional user: 'someuser', password: 'somepass' + authentication: nil, # nil, autodetection - to use certain schema use 'plain', 'login' or 'cram_md5' }, mail_attributes, notification @@ -28,6 +30,9 @@ class Channel::Driver::Smtp if !options.key?(:port) options[:port] = 25 end + if !options.key?(:domain) + options[:domain] = Setting.get('fqdn') + end if !options.key?(:enable_starttls_auto) options[:enable_starttls_auto] = true end @@ -39,10 +44,11 @@ class Channel::Driver::Smtp openssl_verify_mode: options[:openssl_verify_mode], address: options[:host], port: options[:port], - domain: options[:host], + domain: options[:domain], user_name: options[:user], password: options[:password], enable_starttls_auto: options[:enable_starttls_auto], + authentication: options[:authentication], } mail.deliver end diff --git a/lib/core_ext/net/smtp.rb b/lib/core_ext/net/smtp.rb new file mode 100644 index 000000000..4e1fa3f45 --- /dev/null +++ b/lib/core_ext/net/smtp.rb @@ -0,0 +1,52 @@ +# rubocop:disable all +module Net + class SMTP + def do_start(helo_domain, user, secret, authtype) + raise IOError, 'SMTP session already started' if @started + if user or secret + check_auth_method(authtype || DEFAULT_AUTH_TYPE) + check_auth_args user, secret + end + s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do + tcp_socket(@address, @port) + end + logging "Connection opened: #{@address}:#{@port}" + @socket = new_internet_message_io(tls? ? tlsconnect(s) : s) + check_response critical { recv_response() } + do_helo helo_domain + if starttls_always? or (capable_starttls? and starttls_auto?) + unless capable_starttls? + raise SMTPUnsupportedCommand, + "STARTTLS is not supported on this server" + end + starttls + @socket = new_internet_message_io(tlsconnect(s)) + # helo response may be different after STARTTLS + do_helo helo_domain + # ADD auto detection of authtype - https://github.com/zammad/zammad/issues/240 + # set detected authtype based on smtp server capabilities + if !authtype + if auth_capable?(DEFAULT_AUTH_TYPE) + authtype = DEFAULT_AUTH_TYPE + elsif capable_plain_auth? + authtype = 'PLAIN' + elsif capable_login_auth? + authtype = 'LOGIN' + elsif capable_cram_md5_auth? + authtype = 'CRAM-MD5' + end + end + # /ADD auto detection of authtype - https://github.com/zammad/zammad/issues/240 + end + authenticate user, secret, (authtype || DEFAULT_AUTH_TYPE) if user + @started = true + ensure + unless @started + # authentication failed, cancel connection. + s.close if s and not s.closed? + @socket = nil + end + end + end +end +# rubocop:enable all \ No newline at end of file