@@ -340,6 +340,33 @@ def test_auth_rejects_conflicting_args(self):
340340 with self .assertRaises (ValueError ):
341341 self .client .auth ("PLAIN" , authobject = lambda c : b"x" , initial_response = b"y" )
342342
343+ def test_auth_unsupported_mechanism (self ):
344+ with self .assertRaises (poplib .error_proto ):
345+ self .client .auth ("FOO" )
346+
347+ def test_auth_cancel (self ):
348+ def authobject (_challenge ):
349+ return b"*"
350+ with self .assertRaises (poplib .error_proto ):
351+ self .client .auth ("PLAIN" , authobject = authobject )
352+
353+ def test_auth_mechanism_case_insensitive (self ):
354+ secret = b"user\x00 adminuser\x00 password"
355+ # use lowercase mechanism name to ensure server accepts
356+ resp = self .client .auth ("plain" , initial_response = secret )
357+ self .assertStartsWith (resp , b"+OK" )
358+
359+ def test_auth_initial_response_str (self ):
360+ secret = "user\x00 adminuser\x00 password" # str, not bytes
361+ resp = self .client .auth ("PLAIN" , initial_response = secret )
362+ self .assertStartsWith (resp , b"+OK" )
363+
364+ def test_auth_authobject_returns_str (self ):
365+ def authobject (challenge ):
366+ return "user\x00 adminuser\x00 password"
367+ resp = self .client .auth ("PLAIN" , authobject = authobject )
368+ self .assertStartsWith (resp , b"+OK" )
369+
343370 def test_stat (self ):
344371 self .assertEqual (self .client .stat (), (10 , 100 ))
345372
@@ -488,6 +515,9 @@ def __init__(self, conn):
488515 self .push ('+OK dummy pop3 server ready. <timestamp>' )
489516 self .tls_active = True
490517 self .tls_starting = False
518+ # Initialize AUTH state like DummyPOP3Handler to avoid AttributeError
519+ self ._auth_pending = False
520+ self ._auth_mech = None
491521
492522
493523@requires_ssl
0 commit comments