1313
1414# Imports
1515
16+ import base64
1617import binascii
1718import errno
1819import re
1920import socket
2021import sys
21- import base64
2222
2323try :
2424 import ssl
@@ -221,6 +221,7 @@ def pass_(self, pswd):
221221 """
222222 return self ._shortcmd ('PASS %s' % pswd )
223223
224+
224225 def stat (self ):
225226 """Get mailbox status.
226227
@@ -428,18 +429,12 @@ def stls(self, context=None):
428429 return resp
429430
430431 def auth (self , mechanism , authobject , * , initial_response_ok = True ):
431- """Authenticate to the POP3 server using AUTH (RFC 5034).
432-
433- Result is 'response'.
434- """
432+ """Authenticate to the POP3 server using AUTH (RFC 5034)."""
435433 mech = mechanism .upper ()
436434
437435 initial = None
438- if initial_response_ok :
439- try :
440- initial = authobject ()
441- except TypeError :
442- initial = None
436+ if initial_response_ok and callable (authobject ):
437+ initial = authobject ()
443438 if isinstance (initial , str ):
444439 initial = initial .encode ('ascii' , 'strict' )
445440 if initial is not None and not isinstance (initial , (bytes , bytearray )):
@@ -448,7 +443,7 @@ def auth(self, mechanism, authobject, *, initial_response_ok=True):
448443 if initial is not None :
449444 b64 = base64 .b64encode (initial ).decode ('ascii' )
450445 cmd = f'AUTH { mech } { b64 } '
451- if len (cmd .encode ('ascii' )) + 2 <= 255 :
446+ if len (cmd .encode ('ascii' )) <= 253 :
452447 self ._putcmd (cmd )
453448 else :
454449 self ._putcmd (f'AUTH { mech } ' )
@@ -465,12 +460,12 @@ def auth(self, mechanism, authobject, *, initial_response_ok=True):
465460 if line .startswith (b'-ERR' ):
466461 raise error_proto (line .decode ('ascii' , 'replace' ))
467462 # Challenge line: "+ <b64>" or just "+" (empty challenge)
468- if not ( line == b'+' or line .startswith (b'+ ' ) ):
463+ if line != b'+' and not line .startswith (b'+ ' ):
469464 raise error_proto (f'malformed AUTH challenge line: { line !r} ' )
470465
471466 auth_challenge_count += 1
472467 if auth_challenge_count > _MAXCHALLENGE :
473- raise error_proto ('Server AUTH mechanism infinite loop' )
468+ raise error_proto ('Server AUTH mechanism infinite loop. Last response: ' , repr ( line ) )
474469
475470 chal = line [1 :]
476471 if chal .startswith (b' ' ):
@@ -500,10 +495,7 @@ def auth(self, mechanism, authobject, *, initial_response_ok=True):
500495 self ._putcmd (base64 .b64encode (resp ).decode ('ascii' ))
501496
502497 def auth_plain (self , user , password , authzid = '' ):
503- """Return an authobject suitable for SASL PLAIN.
504-
505- Result is 'str'.
506- """
498+ """Return an authobject suitable for SASL PLAIN."""
507499 def _auth_plain (challenge = None ):
508500 # Per RFC 4616, the response is: authzid UTF8 NUL authcid UTF8 NUL passwd UTF8
509501 return f"{ authzid } \0 { user } \0 { password } "
0 commit comments