@@ -926,11 +926,15 @@ def _auth_cram_md5(self, arg=None):
926926            except  ValueError  as  e :
927927                self .push ('535 Splitting response {!r} into user and password ' 
928928                          'failed: {}' .format (logpass , e ))
929-                 return  False 
930-             valid_hashed_pass  =  hmac .HMAC (
931-                 sim_auth [1 ].encode ('ascii' ),
932-                 self ._decode_base64 (sim_cram_md5_challenge ).encode ('ascii' ),
933-                 'md5' ).hexdigest ()
929+                 return 
930+ 
931+             pwd  =  sim_auth [1 ].encode ('ascii' )
932+             msg  =  self ._decode_base64 (sim_cram_md5_challenge ).encode ('ascii' )
933+             try :
934+                 valid_hashed_pass  =  hmac .HMAC (pwd , msg , 'md5' ).hexdigest ()
935+             except  ValueError :
936+                 self .push ('504 CRAM-MD5 is not supported' )
937+                 return 
934938            self ._authenticated (user , hashed_pass  ==  valid_hashed_pass )
935939    # end AUTH related stuff. 
936940
@@ -1031,6 +1035,7 @@ def handle_error(self):
10311035class  SMTPSimTests (unittest .TestCase ):
10321036
10331037    def  setUp (self ):
1038+         smtplib ._have_cram_md5_support .cache_clear ()
10341039        self .thread_key  =  threading_helper .threading_setup ()
10351040        self .real_getfqdn  =  socket .getfqdn 
10361041        socket .getfqdn  =  mock_socket .getfqdn 
@@ -1181,6 +1186,29 @@ def testAUTH_CRAM_MD5(self):
11811186        self .assertEqual (resp , (235 , b'Authentication Succeeded' ))
11821187        smtp .close ()
11831188
1189+     @hashlib_helper .block_algorithm ('md5' ) 
1190+     def  testAUTH_CRAM_MD5_blocked (self ):
1191+         # CRAM-MD5 is the only "known" method by the server, 
1192+         # but it is not supported by the client. In particular, 
1193+         # no challenge will ever be sent. 
1194+         self .serv .add_feature ("AUTH CRAM-MD5" )
1195+         smtp  =  smtplib .SMTP (HOST , self .port , local_hostname = 'localhost' ,
1196+                             timeout = support .LOOPBACK_TIMEOUT )
1197+         self .addCleanup (smtp .close )
1198+         msg  =  re .escape ("No suitable authentication method found." )
1199+         with  self .assertRaisesRegex (smtplib .SMTPException , msg ):
1200+             smtp .login (sim_auth [0 ], sim_auth [1 ])
1201+ 
1202+     @hashlib_helper .block_algorithm ('md5' ) 
1203+     def  testAUTH_CRAM_MD5_blocked_and_fallback (self ):
1204+         # Test that PLAIN is tried after CRAM-MD5 failed 
1205+         self .serv .add_feature ("AUTH CRAM-MD5 PLAIN" )
1206+         smtp  =  smtplib .SMTP (HOST , self .port , local_hostname = 'localhost' ,
1207+                             timeout = support .LOOPBACK_TIMEOUT )
1208+         self .addCleanup (smtp .close )
1209+         resp  =  smtp .login (sim_auth [0 ], sim_auth [1 ])
1210+         self .assertEqual (resp , (235 , b'Authentication Succeeded' ))
1211+ 
11841212    @hashlib_helper .requires_hashdigest ('md5' , openssl = True ) 
11851213    def  testAUTH_multiple (self ):
11861214        # Test that multiple authentication methods are tried. 
0 commit comments