diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index 9b8ff4e..e962c04 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -31,6 +31,17 @@ module Net module SMTPError # This *class* is a module for backward compatibility. # In later release, this module becomes a class. + + attr_reader :response + + def initialize(response, message: nil) + @response = response + @message = message + end + + def message + @message || response.message + end end # Represents an SMTP authentication error. @@ -609,8 +620,7 @@ def do_start(helo_domain, user, secret, authtype) do_helo helo_domain if ! tls? and (starttls_always? or (capable_starttls? and starttls_auto?)) unless capable_starttls? - raise SMTPUnsupportedCommand, - "STARTTLS is not supported on this server" + raise SMTPUnsupportedCommand.new(nil, message: "STARTTLS is not supported on this server") end starttls @socket = new_internet_message_io(tlsconnect(s, @ssl_context_starttls)) @@ -1013,25 +1023,25 @@ def critical def check_response(res) unless res.success? - raise res.exception_class, res.message + raise res.exception_class.new(res) end end def check_continue(res) unless res.continue? - raise SMTPUnknownError, "could not get 3xx (#{res.status}: #{res.string})" + raise SMTPUnknownError.new(res, message: "could not get 3xx (#{res.status}: #{res.string})") end end def check_auth_response(res) unless res.success? - raise SMTPAuthenticationError, res.message + raise SMTPAuthenticationError.new(res) end end def check_auth_continue(res) unless res.continue? - raise res.exception_class, res.message + raise res.exception_class.new(res) end end diff --git a/test/net/smtp/test_smtp.rb b/test/net/smtp/test_smtp.rb index 8a5f8db..dc1d962 100644 --- a/test/net/smtp/test_smtp.rb +++ b/test/net/smtp/test_smtp.rb @@ -101,6 +101,93 @@ def test_auth_plain assert_equal "AUTH PLAIN AGZvbwBiYXI=\r\n", sock.write_io.string end + def test_unsucessful_auth_plain + sock = FakeSocket.new("535 Authentication failed: FAIL\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPAuthenticationError) { smtp.auth_plain("foo", "bar") } + assert_equal "535 Authentication failed: FAIL\n", err.message + assert_equal "535", err.response.status + end + + def test_auth_login + sock = FakeSocket.new("334 VXNlcm5hbWU6\r\n334 UGFzc3dvcmQ6\r\n235 2.7.0 Authentication successful\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + assert smtp.auth_login("foo", "bar").success? + end + + def test_unsucessful_auth_login + sock = FakeSocket.new("334 VXNlcm5hbWU6\r\n334 UGFzc3dvcmQ6\r\n535 Authentication failed: FAIL\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPAuthenticationError) { smtp.auth_login("foo", "bar") } + assert_equal "535 Authentication failed: FAIL\n", err.message + assert_equal "535", err.response.status + end + + def test_non_continue_auth_login + sock = FakeSocket.new("334 VXNlcm5hbWU6\r\n235 2.7.0 Authentication successful\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPUnknownError) { smtp.auth_login("foo", "bar") } + assert_equal "235 2.7.0 Authentication successful\n", err.message + assert_equal "235", err.response.status + end + + def test_unsuccessful_send_message_server_busy + sock = FakeSocket.new("400 BUSY\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPServerBusy) { smtp.send_message('message', 'ojab@example.com') } + assert_equal "400 BUSY\n", err.message + assert_equal "400", err.response.status + end + + def test_unsuccessful_send_message_syntax_error + sock = FakeSocket.new("502 SYNTAX ERROR\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPSyntaxError) { smtp.send_message('message', 'ojab@example.com') } + assert_equal "502 SYNTAX ERROR\n", err.message + assert_equal "502", err.response.status + end + + def test_unsuccessful_send_message_authentication_error + sock = FakeSocket.new("530 AUTH ERROR\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPAuthenticationError) { smtp.send_message('message', 'ojab@example.com') } + assert_equal "530 AUTH ERROR\n", err.message + assert_equal "530", err.response.status + end + + def test_unsuccessful_send_message_fatal_error + sock = FakeSocket.new("520 FATAL ERROR\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPFatalError) { smtp.send_message('message', 'ojab@example.com') } + assert_equal "520 FATAL ERROR\n", err.message + assert_equal "520", err.response.status + end + + def test_unsuccessful_send_message_unknown_error + sock = FakeSocket.new("300 UNKNOWN\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPUnknownError) { smtp.send_message('message', 'ojab@example.com') } + assert_equal "300 UNKNOWN\n", err.message + assert_equal "300", err.response.status + end + + def test_unsuccessful_data + sock = FakeSocket.new("250 OK\r\n") + smtp = Net::SMTP.new 'localhost', 25 + smtp.instance_variable_set :@socket, sock + err = assert_raise(Net::SMTPUnknownError) { smtp.data('message') } + assert_equal "could not get 3xx (250: 250 OK\n)", err.response.status + end + def test_crlf_injection smtp = Net::SMTP.new 'localhost', 25 smtp.instance_variable_set :@socket, FakeSocket.new diff --git a/test/net/smtp/test_starttls.rb b/test/net/smtp/test_starttls.rb index 096eaad..f2bb201 100644 --- a/test/net/smtp/test_starttls.rb +++ b/test/net/smtp/test_starttls.rb @@ -76,6 +76,7 @@ def test_enable_starttls_without_starttls_capable smtp.enable_starttls err = assert_raise(Net::SMTPUnsupportedCommand) { smtp.start } assert_equal("STARTTLS is not supported on this server", err.message) + assert_nil(err.response) end def test_enable_starttls_auto_with_starttls_capable