From c933c3e367006593c4e8e871f6d7aa64cb6d5111 Mon Sep 17 00:00:00 2001 From: nicholas evans Date: Wed, 11 Oct 2023 00:54:30 -0400 Subject: [PATCH] Add keyword parameters to authenticators Username can be set by args[0], authcid, username, or user. Secret can be set by args[1], secret, or password. Since all of the existing authenticators have the same API, it is sufficient to update `check_args` in the base class. --- lib/net/smtp/auth_cram_md5.rb | 7 ++++++- lib/net/smtp/auth_login.rb | 7 ++++++- lib/net/smtp/auth_plain.rb | 7 ++++++- lib/net/smtp/authenticator.rb | 15 ++++++++++++--- test/net/smtp/test_smtp.rb | 9 +++++++++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/net/smtp/auth_cram_md5.rb b/lib/net/smtp/auth_cram_md5.rb index 0490cd6..50994ee 100644 --- a/lib/net/smtp/auth_cram_md5.rb +++ b/lib/net/smtp/auth_cram_md5.rb @@ -9,7 +9,12 @@ class Net::SMTP class AuthCramMD5 < Net::SMTP::Authenticator auth_type :cram_md5 - def auth(user, secret) + def auth(user_arg = nil, secret_arg = nil, + authcid: nil, username: nil, user: nil, + secret: nil, password: nil, + **) + user = req_param authcid, username, user, user_arg, "username (authcid)" + secret = req_param password, secret, secret_arg, "secret (password)" challenge = continue('AUTH CRAM-MD5') crammed = cram_md5_response(secret, challenge.unpack1('m')) finish(base64_encode("#{user} #{crammed}")) diff --git a/lib/net/smtp/auth_login.rb b/lib/net/smtp/auth_login.rb index 545c1f9..174ab09 100644 --- a/lib/net/smtp/auth_login.rb +++ b/lib/net/smtp/auth_login.rb @@ -2,7 +2,12 @@ class Net::SMTP class AuthLogin < Net::SMTP::Authenticator auth_type :login - def auth(user, secret) + def auth(user_arg = nil, secret_arg = nil, + authcid: nil, username: nil, user: nil, + secret: nil, password: nil, + **) + user = req_param authcid, username, user, user_arg, "username (authcid)" + secret = req_param password, secret, secret_arg, "secret (password)" continue('AUTH LOGIN') continue(base64_encode(user)) finish(base64_encode(secret)) diff --git a/lib/net/smtp/auth_plain.rb b/lib/net/smtp/auth_plain.rb index 7fa1198..e778bad 100644 --- a/lib/net/smtp/auth_plain.rb +++ b/lib/net/smtp/auth_plain.rb @@ -2,7 +2,12 @@ class Net::SMTP class AuthPlain < Net::SMTP::Authenticator auth_type :plain - def auth(user, secret) + def auth(user_arg = nil, secret_arg = nil, + authcid: nil, username: nil, user: nil, + secret: nil, password: nil, + **) + user = req_param authcid, username, user, user_arg, "username (authcid)" + secret = req_param password, secret, secret_arg, "secret (password)" finish('AUTH PLAIN ' + base64_encode("\0#{user}\0#{secret}")) end end diff --git a/lib/net/smtp/authenticator.rb b/lib/net/smtp/authenticator.rb index 4e91228..6e381af 100644 --- a/lib/net/smtp/authenticator.rb +++ b/lib/net/smtp/authenticator.rb @@ -15,11 +15,14 @@ def self.auth_class(type) Authenticator.auth_classes[type] end - def self.check_args(user_arg = nil, secret_arg = nil, *, **) - unless user_arg + def self.check_args(user_arg = nil, secret_arg = nil, *, + authcid: nil, username: nil, user: nil, + secret: nil, password: nil, + **) + unless authcid || username || user || user_arg raise ArgumentError, 'SMTP-AUTH requested but missing user name' end - unless secret_arg + unless password || secret || secret_arg raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase' end end @@ -52,6 +55,12 @@ def base64_encode(str) # expects "str" may not become too long [str].pack('m0') end + + def req_param(*args, name) + args.compact.first or + raise ArgumentError, "SMTP-AUTH requested but missing #{name}" + end + end end end diff --git a/test/net/smtp/test_smtp.rb b/test/net/smtp/test_smtp.rb index 85bc1bc..a4450b3 100644 --- a/test/net/smtp/test_smtp.rb +++ b/test/net/smtp/test_smtp.rb @@ -455,6 +455,15 @@ def test_start_auth_plain port = fake_server_start(auth: 'plain') Net::SMTP.start('localhost', port, user: 'account', password: 'password', authtype: :plain){} + port = fake_server_start(auth: 'plain') + Net::SMTP.start('localhost', port, authtype: "PLAIN", + auth: {username: 'account', password: 'password'}){} + + port = fake_server_start(auth: 'plain') + Net::SMTP.start('localhost', port, auth: {username: 'account', + password: 'password', + type: :plain}){} + port = fake_server_start(auth: 'plain') assert_raise Net::SMTPAuthenticationError do Net::SMTP.start('localhost', port, user: 'account', password: 'invalid', authtype: :plain){}