summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerhard Häring <gh@ghaering.de>2010-08-05 14:08:44 (GMT)
committerGerhard Häring <gh@ghaering.de>2010-08-05 14:08:44 (GMT)
commit1c5471f319a4e5c7bbb56c7ae349b5fe455dc857 (patch)
tree016a8aefb889ab62ac9863ed932d09a58b32e361
parentae7801813c56464e08f7a29c917aa2bc1326831b (diff)
downloadcpython-1c5471f319a4e5c7bbb56c7ae349b5fe455dc857.zip
cpython-1c5471f319a4e5c7bbb56c7ae349b5fe455dc857.tar.gz
cpython-1c5471f319a4e5c7bbb56c7ae349b5fe455dc857.tar.bz2
Issue #6683: For SMTP logins we now try all authentication methods advertised
by the server. Many servers are buggy and advertise authentication methods they o not support in reality. This change makes smtplib.auth() work more often in the real world, where we face misconfigured servers and servers that advertise methods they don't support due to the madness that is SASL.
-rwxr-xr-xLib/smtplib.py57
-rw-r--r--Misc/NEWS4
2 files changed, 33 insertions, 28 deletions
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index 69ec9ec..1c1a9d1 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -559,43 +559,44 @@ class SMTP:
if not self.has_extn("auth"):
raise SMTPException("SMTP AUTH extension not supported by server.")
- # Authentication methods the server supports:
- authlist = self.esmtp_features["auth"].split()
+ # Authentication methods the server claims to support
+ advertised_authlist = self.esmtp_features["auth"].split()
# List of authentication methods we support: from preferred to
# less preferred methods. Except for the purpose of testing the weaker
# ones, we prefer stronger methods like CRAM-MD5:
preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]
- # Determine the authentication method we'll use
- authmethod = None
- for method in preferred_auths:
- if method in authlist:
- authmethod = method
- break
-
- if authmethod == AUTH_CRAM_MD5:
- (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
- if code == 503:
- # 503 == 'Error: already authenticated'
- return (code, resp)
- (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
- elif authmethod == AUTH_PLAIN:
- (code, resp) = self.docmd("AUTH",
- AUTH_PLAIN + " " + encode_plain(user, password))
- elif authmethod == AUTH_LOGIN:
- (code, resp) = self.docmd("AUTH",
- "%s %s" % (AUTH_LOGIN, encode_base64(user.encode('ascii'), eol='')))
- if code != 334:
- raise SMTPAuthenticationError(code, resp)
- (code, resp) = self.docmd(encode_base64(password.encode('ascii'), eol=''))
- elif authmethod is None:
+ # We try the authentication methods the server advertises, but only the
+ # ones *we* support. And in our preferred order.
+ authlist = [auth for auth in preferred_auths if auth in advertised_authlist]
+ if not authlist:
raise SMTPException("No suitable authentication method found.")
- if code not in (235, 503):
+
+ # Some servers advertise authentication methods they don't really
+ # support, so if authentication fails, we continue until we've tried
+ # all methods.
+ for authmethod in authlist:
+ if authmethod == AUTH_CRAM_MD5:
+ (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
+ if code == 334:
+ (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
+ elif authmethod == AUTH_PLAIN:
+ (code, resp) = self.docmd("AUTH",
+ AUTH_PLAIN + " " + encode_plain(user, password))
+ elif authmethod == AUTH_LOGIN:
+ (code, resp) = self.docmd("AUTH",
+ "%s %s" % (AUTH_LOGIN, encode_base64(user.encode('ascii'), eol='')))
+ if code == 334:
+ (code, resp) = self.docmd(encode_base64(password.encode('ascii'), eol=''))
+
# 235 == 'Authentication successful'
# 503 == 'Error: already authenticated'
- raise SMTPAuthenticationError(code, resp)
- return (code, resp)
+ if code in (235, 503):
+ return (code, resp)
+
+ # We could not login sucessfully. Return result of last attempt.
+ raise SMTPAuthenticationError(code, resp)
def starttls(self, keyfile = None, certfile = None):
"""Puts the connection to the SMTP server into TLS mode.
diff --git a/Misc/NEWS b/Misc/NEWS
index 4594a88..fe93e4e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -40,6 +40,10 @@ Extensions
Library
-------
+- Issue #6683: For SMTP logins we now try all authentication methods advertised
+ by the server. Many servers are buggy and advertise authentication methods they
+ o not support in reality.
+
- Issue #8814: function annotations (the ``__annotations__`` attribute)
are now included in the set of attributes copied by default by
functools.wraps and functools.update_wrapper. Patch by Terrence Cole.