@@ -420,6 +420,15 @@ def cmd_AUTHENTICATE(self, tag, args):
420420 self ._send_tagged (tag , 'NO' , 'No access' )
421421
422422
423+ class AuthHandler_PLAIN (SimpleIMAPHandler ):
424+ capabilities = 'LOGINDISABLED AUTH=PLAIN'
425+ def cmd_AUTHENTICATE (self , tag , args ):
426+ self .server .auth_args = args
427+ self ._send_textline ('+' )
428+ self .server .response = yield
429+ self ._send_tagged (tag , 'OK' , 'Logged in.' )
430+
431+
423432class NewIMAPTestsMixin :
424433 client = None
425434
@@ -692,6 +701,35 @@ def test_login_cram_md5_blocked(self):
692701 with self .assertRaisesRegex (imaplib .IMAP4 .error , msg ):
693702 client .login_cram_md5 ("tim" , b"tanstaaftanstaaf" )
694703
704+ def test_login_plain_ascii (self ):
705+ client , server = self ._setup (AuthHandler_PLAIN )
706+ self .assertIn ('AUTH=PLAIN' , client .capabilities )
707+ ret , _ = client .login_plain ("prem" , "pass" )
708+ self .assertEqual (ret , "OK" )
709+ self .assertEqual (server .auth_args , ['PLAIN' ])
710+ self .assertEqual (server .response , b'AHByZW0AcGFzcw==\r \n ' )
711+
712+ def test_login_plain_utf8 (self ):
713+ client , server = self ._setup (AuthHandler_PLAIN )
714+ self .assertIn ('AUTH=PLAIN' , client .capabilities )
715+ ret , _ = client .login_plain ("pręm" , "żółć" )
716+ self .assertEqual (ret , "OK" )
717+ self .assertEqual (server .response , b'AHByxJltAMW8w7PFgsSH\r \n ' )
718+
719+ def test_login_plain_bytes (self ):
720+ # bytes are accepted and sent verbatim (not re-encoded).
721+ client , server = self ._setup (AuthHandler_PLAIN )
722+ ret , _ = client .login_plain (b'pr\xc4 \x99 m' , b'\xc5 \xbc \xc3 \xb3 \xc5 \x82 \xc4 \x87 ' )
723+ self .assertEqual (ret , "OK" )
724+ self .assertEqual (server .response , b'AHByxJltAMW8w7PFgsSH\r \n ' )
725+
726+ def test_login_plain_nul (self ):
727+ client , _ = self ._setup (AuthHandler_PLAIN )
728+ with self .assertRaises (ValueError ):
729+ client .login_plain ('user\0 ' , 'pass' )
730+ with self .assertRaises (ValueError ):
731+ client .login_plain ('user' , b'pa\0 ss' )
732+
695733 def test_aborted_authentication (self ):
696734 class MyServer (SimpleIMAPHandler ):
697735 def cmd_AUTHENTICATE (self , tag , args ):
@@ -1701,6 +1739,24 @@ def test_getquotaroot(self):
17011739 self .assertEqual (typ , 'OK' )
17021740 self .assertEqual (server .args , ['"New folder"' ])
17031741
1742+ def test_id (self ):
1743+ client , server = self ._setup (make_simple_handler ('ID' ,
1744+ ['* ID ("name" "Cyrus" "version" "1.5")' ]))
1745+ typ , data = client .id ({'name' : 'imaplib' , 'version' : '3.16' })
1746+ self .assertEqual (typ , 'OK' )
1747+ self .assertEqual (data , [b'("name" "Cyrus" "version" "1.5")' ])
1748+ self .assertEqual (server .args , ['("name" "imaplib" "version" "3.16")' ])
1749+
1750+ typ , data = client .id ()
1751+ self .assertEqual (typ , 'OK' )
1752+ self .assertEqual (server .args , ['NIL' ])
1753+
1754+ # Fields and values are quoted strings; a None value is sent
1755+ # as NIL.
1756+ typ , data = client .id ({'name' : 'my "client"' , 'os' : None })
1757+ self .assertEqual (typ , 'OK' )
1758+ self .assertEqual (server .args , [r'("name" "my \"client\"" "os" NIL)' ])
1759+
17041760 def test_setquota (self ):
17051761 client , server = self ._setup (make_simple_handler ('SETQUOTA' ,
17061762 ['* QUOTA "" (STORAGE 512)' ]))
0 commit comments