diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index dcf28d1..a87e48d 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -409,14 +409,14 @@ def debug_output=(arg) # # :call-seq: - # start(address, port = nil, helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true) { |smtp| ... } + # start(address, port = nil, helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true, tls_hostname: nil) { |smtp| ... } # start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... } # # Creates a new Net::SMTP object and connects to the server. # # This method is equivalent to: # - # Net::SMTP.new(address, port).start(helo: helo_domain, user: account, secret: password, authtype: authtype, tls_verify: flag) + # Net::SMTP.new(address, port).start(helo: helo_domain, user: account, secret: password, authtype: authtype, tls_verify: flag, tls_hostname: hostname) # # === Example # @@ -447,6 +447,8 @@ def debug_output=(arg) # type, one of :plain, :login, or :cram_md5. See the discussion of # SMTP Authentication in the overview notes. # If +tls_verify+ is true, verify the server's certificate. The default is true. + # If the hostname in the server certificate is different from +address+, + # it can be specified with +tls_hostname+. # # === Errors # @@ -462,14 +464,15 @@ def debug_output=(arg) # * IOError # def SMTP.start(address, port = nil, *args, helo: nil, - user: nil, secret: nil, password: nil, authtype: nil, tls_verify: true, + user: nil, secret: nil, password: nil, authtype: nil, + tls_verify: true, tls_hostname: nil, &block) raise ArgumentError, "wrong number of arguments (given #{args.size + 2}, expected 1..6)" if args.size > 4 helo ||= args[0] || 'localhost' user ||= args[1] secret ||= password || args[2] authtype ||= args[3] - new(address, port).start(helo: helo, user: user, secret: secret, authtype: authtype, tls_verify: tls_verify, &block) + new(address, port).start(helo: helo, user: user, secret: secret, authtype: authtype, tls_verify: tls_verify, tls_hostname: tls_hostname, &block) end # +true+ if the SMTP session has been started. @@ -479,7 +482,7 @@ def started? # # :call-seq: - # start(helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true) { |smtp| ... } + # start(helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true, tls_hostname: nil) { |smtp| ... } # start(helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... } # # Opens a TCP connection and starts the SMTP session. @@ -495,6 +498,8 @@ def started? # :login, :plain, and :cram_md5. See the notes on SMTP Authentication # in the overview. # If +tls_verify+ is true, verify the server's certificate. The default is true. + # If the hostname in the server certificate is different from +address+, + # it can be specified with +tls_hostname+. # # === Block Usage # @@ -534,7 +539,7 @@ def started? # * IOError # def start(*args, helo: nil, - user: nil, secret: nil, password: nil, authtype: nil, tls_verify: true) + user: nil, secret: nil, password: nil, authtype: nil, tls_verify: true, tls_hostname: nil) raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..4)" if args.size > 4 helo ||= args[0] || 'localhost' user ||= args[1] @@ -546,6 +551,7 @@ def start(*args, helo: nil, if @starttls && @ssl_context_starttls.nil? @ssl_context_starttls = SMTP.default_ssl_context(tls_verify) end + @tls_hostname = tls_hostname if block_given? begin do_start helo, user, secret, authtype @@ -614,10 +620,10 @@ def tlsconnect(s, context) s = ssl_socket(s, context) logging "TLS connection started" s.sync_close = true - s.hostname = @address if s.respond_to? :hostname= + s.hostname = @tls_hostname || @address if s.respond_to? :hostname= ssl_socket_connect(s, @open_timeout) if context.verify_mode && context.verify_mode != OpenSSL::SSL::VERIFY_NONE - s.post_connection_check(@address) + s.post_connection_check(@tls_hostname || @address) end verified = true s diff --git a/test/net/smtp/test_sslcontext.rb b/test/net/smtp/test_sslcontext.rb index a72ade5..f3f3b34 100644 --- a/test/net/smtp/test_sslcontext.rb +++ b/test/net/smtp/test_sslcontext.rb @@ -4,7 +4,7 @@ module Net class TestSSLContext < Test::Unit::TestCase class MySMTP < SMTP - attr_reader :__ssl_context + attr_reader :__ssl_context, :__tls_hostname def initialize(socket) @fake_socket = socket @@ -26,7 +26,8 @@ def tlsconnect(*) def ssl_socket(socket, context) @__ssl_context = context s = super - s.define_singleton_method(:post_connection_check){|_|} + hostname = @__tls_hostname = '' + s.define_singleton_method(:post_connection_check){ |name| hostname.replace(name) } s end end @@ -110,5 +111,18 @@ def test_start_with_tls_verify_false smtp.start(tls_verify: false) assert_equal(OpenSSL::SSL::VERIFY_NONE, smtp.__ssl_context.verify_mode) end + + def test_start_with_tls_hostname + smtp = MySMTP.new(start_smtpd(true)) + smtp.start(tls_hostname: "localhost") + assert_equal("localhost", smtp.__tls_hostname) + end + + def test_start_without_tls_hostname + smtp = MySMTP.new(start_smtpd(true)) + smtp.start + assert_equal("smtp.example.com", smtp.__tls_hostname) + end + end end