@@ -43,7 +43,7 @@ class Session:
4343 >>> import proton
4444 >>> s = proton.Session("https://url-to-api.ch")
4545 >>> s.enable_alternative_routing = True
46- >>> s.api_request(' /api/endpoint' )
46+ >>> s.api_request(" /api/endpoint" )
4747 <Response [200]>
4848 """
4949 _base_headers = {
@@ -73,10 +73,10 @@ def load(
7373 Returns:
7474 proton.Session
7575 """
76- api_url = dump [' api_url' ]
77- appversion = dump [' appversion' ]
78- user_agent = dump [' User-Agent' ]
79- cookies = dump .get (' cookies' , {})
76+ api_url = dump [" api_url" ]
77+ appversion = dump [" appversion" ]
78+ user_agent = dump [" User-Agent" ]
79+ cookies = dump .get (" cookies" , {})
8080 s = Session (
8181 api_url = api_url ,
8282 log_dir_path = log_dir_path ,
@@ -88,10 +88,10 @@ def load(
8888 proxies = proxies
8989 )
9090 requests .utils .add_dict_to_cookiejar (s .s .cookies , cookies )
91- s ._session_data = dump [' session_data' ]
91+ s ._session_data = dump [" session_data" ]
9292 if s .UID is not None :
93- s .s .headers [' x-pm-uid' ] = s .UID
94- s .s .headers [' Authorization' ] = ' Bearer ' + s .AccessToken
93+ s .s .headers [" x-pm-uid" ] = s .UID
94+ s .s .headers [" Authorization" ] = " Bearer " + s .AccessToken
9595 return s
9696
9797 def dump (self ):
@@ -104,11 +104,11 @@ def dump(self):
104104 dict
105105 """
106106 return {
107- ' api_url' : self .__api_url ,
108- ' appversion' : self .__appversion ,
109- ' User-Agent' : self .__user_agent ,
110- ' cookies' : self .s .cookies .get_dict (),
111- ' session_data' : self ._session_data
107+ " api_url" : self .__api_url ,
108+ " appversion" : self .__appversion ,
109+ " User-Agent" : self .__user_agent ,
110+ " cookies" : self .s .cookies .get_dict (),
111+ " session_data" : self ._session_data
112112 }
113113
114114 def __init__ (
@@ -165,8 +165,8 @@ def __init__(
165165 if self .__tls_pinning_enabled :
166166 self .s .mount (self .__api_url , TLSPinningAdapter ())
167167
168- self .s .headers [' x-pm-appversion' ] = appversion
169- self .s .headers [' User-Agent' ] = user_agent
168+ self .s .headers [" x-pm-appversion" ] = appversion
169+ self .s .headers [" User-Agent" ] = user_agent
170170
171171 def api_request (
172172 self , endpoint ,
@@ -205,11 +205,11 @@ def api_request(
205205 fct = self .s .post
206206 else :
207207 fct = {
208- ' get' : self .s .get ,
209- ' post' : self .s .post ,
210- ' put' : self .s .put ,
211- ' delete' : self .s .delete ,
212- ' patch' : self .s .patch
208+ " get" : self .s .get ,
209+ " post" : self .s .post ,
210+ " put" : self .s .put ,
211+ " delete" : self .s .delete ,
212+ " patch" : self .s .patch
213213 }.get (method .lower ())
214214
215215 if fct is None :
@@ -273,8 +273,8 @@ def api_request(
273273 }
274274 )
275275
276- if response [' Code' ] not in [1000 , 1001 ]:
277- if response [' Code' ] == 9001 :
276+ if response [" Code" ] not in [1000 , 1001 ]:
277+ if response [" Code" ] == 9001 :
278278 self .__captcha_token = response ["Details" ]["HumanVerificationToken" ]
279279
280280 raise ProtonAPIError (response )
@@ -344,7 +344,7 @@ def verify_modulus(self, armored_modulus):
344344 verified = self .__gnupg .decrypt (armored_modulus )
345345
346346 if not (verified .valid and verified .fingerprint .lower () == SRP_MODULUS_KEY_FINGERPRINT ):
347- raise ValueError (' Invalid modulus' )
347+ raise ValueError (" Invalid modulus" )
348348
349349 return base64 .b64decode (verified .data .strip ())
350350
@@ -365,7 +365,7 @@ def authenticate(self, username, password, human_verification=None):
365365
366366 payload = {"Username" : username }
367367 if self .__clientsecret :
368- payload [' ClientSecret' ] = self .__clientsecret
368+ payload [" ClientSecret" ] = self .__clientsecret
369369
370370 additional_headers = {}
371371
@@ -381,7 +381,7 @@ def authenticate(self, username, password, human_verification=None):
381381 additional_headers = additional_headers
382382 )
383383
384- modulus = self .verify_modulus (info_response [' Modulus' ])
384+ modulus = self .verify_modulus (info_response [" Modulus" ])
385385 server_challenge = base64 .b64decode (info_response ["ServerEphemeral" ])
386386 salt = base64 .b64decode (info_response ["Salt" ])
387387 version = info_response ["Version" ]
@@ -391,38 +391,39 @@ def authenticate(self, username, password, human_verification=None):
391391 client_proof = usr .process_challenge (salt , server_challenge , version )
392392
393393 if client_proof is None :
394- raise ValueError (' Invalid challenge' )
394+ raise ValueError (" Invalid challenge" )
395395
396396 # Send response
397397 payload = {
398398 "Username" : username ,
399399 "ClientEphemeral" : base64 .b64encode (client_challenge ).decode (
400- ' utf8'
400+ " utf8"
401401 ),
402- "ClientProof" : base64 .b64encode (client_proof ).decode (' utf8' ),
402+ "ClientProof" : base64 .b64encode (client_proof ).decode (" utf8" ),
403403 "SRPSession" : info_response ["SRPSession" ],
404404 }
405405 if self .__clientsecret :
406- payload [' ClientSecret' ] = self .__clientsecret
406+ payload [" ClientSecret" ] = self .__clientsecret
407407 auth_response = self .api_request ("/auth" , payload )
408408
409409 if "ServerProof" not in auth_response :
410410 raise ValueError ("Invalid password" )
411411
412412 usr .verify_session (base64 .b64decode (auth_response ["ServerProof" ]))
413413 if not usr .authenticated ():
414- raise ValueError (' Invalid server proof' )
414+ raise ValueError (" Invalid server proof" )
415415
416416 self ._session_data = {
417- 'UID' : auth_response ["UID" ],
418- 'AccessToken' : auth_response ["AccessToken" ],
419- 'RefreshToken' : auth_response ["RefreshToken" ],
420- 'Scope' : auth_response ["Scope" ].split (),
417+ "UID" : auth_response ["UID" ],
418+ "AccessToken" : auth_response ["AccessToken" ],
419+ "RefreshToken" : auth_response ["RefreshToken" ],
420+ "PasswordMode" : auth_response ["PasswordMode" ],
421+ "Scope" : auth_response ["Scope" ].split (),
421422 }
422423
423424 if self .UID is not None :
424- self .s .headers [' x-pm-uid' ] = self .UID
425- self .s .headers [' Authorization' ] = ' Bearer ' + self .AccessToken
425+ self .s .headers [" x-pm-uid" ] = self .UID
426+ self .s .headers [" Authorization" ] = " Bearer " + self .AccessToken
426427
427428 return self .Scope
428429
@@ -438,17 +439,17 @@ def provide_2fa(self, code):
438439 The returning dict contains the Scope of the account. This allows
439440 to identify if the account is locked, has unpaid invoices, etc.
440441 """
441- ret = self .api_request (' /auth/2fa' , {"TwoFactorCode" : code })
442- self ._session_data [' Scope' ] = ret [' Scope' ]
442+ ret = self .api_request (" /auth/2fa" , {"TwoFactorCode" : code })
443+ self ._session_data [" Scope" ] = ret [" Scope" ]
443444
444445 return self .Scope
445446
446447 def logout (self ):
447448 """Logout from API."""
448449 if self ._session_data :
449- self .api_request (' /auth' , method = ' DELETE' )
450- del self .s .headers [' Authorization' ]
451- del self .s .headers [' x-pm-uid' ]
450+ self .api_request (" /auth" , method = " DELETE" )
451+ del self .s .headers [" Authorization" ]
452+ del self .s .headers [" x-pm-uid" ]
452453 self ._session_data = {}
453454
454455 def refresh (self ):
@@ -459,17 +460,17 @@ def refresh(self):
459460 re-authenticate.
460461 """
461462 refresh_response = self .api_request (
462- ' /auth/refresh' ,
463+ " /auth/refresh" ,
463464 {
464465 "ResponseType" : "token" ,
465466 "GrantType" : "refresh_token" ,
466467 "RefreshToken" : self .RefreshToken ,
467468 "RedirectURI" : "http://protonmail.ch"
468469 }
469470 )
470- self ._session_data [' AccessToken' ] = refresh_response ["AccessToken" ]
471- self ._session_data [' RefreshToken' ] = refresh_response ["RefreshToken" ]
472- self .s .headers [' Authorization' ] = ' Bearer ' + self .AccessToken
471+ self ._session_data [" AccessToken" ] = refresh_response ["AccessToken" ]
472+ self ._session_data [" RefreshToken" ] = refresh_response ["RefreshToken" ]
473+ self .s .headers [" Authorization" ] = " Bearer " + self .AccessToken
473474
474475 def get_alternative_routes_from_dns (self , callback = None ):
475476 """Get alternative routes to circumvent firewalls and API restrictions.
@@ -642,16 +643,20 @@ def force_skip_alternative_routing(self, newvalue):
642643
643644 @property
644645 def UID (self ):
645- return self ._session_data .get (' UID' , None )
646+ return self ._session_data .get (" UID" , None )
646647
647648 @property
648649 def AccessToken (self ):
649- return self ._session_data .get (' AccessToken' , None )
650+ return self ._session_data .get (" AccessToken" , None )
650651
651652 @property
652653 def RefreshToken (self ):
653- return self ._session_data .get ('RefreshToken' , None )
654+ return self ._session_data .get ("RefreshToken" , None )
655+
656+ @property
657+ def PasswordMode (self ):
658+ return self ._session_data .get ("PasswordMode" , None )
654659
655660 @property
656661 def Scope (self ):
657- return self ._session_data .get (' Scope' , [])
662+ return self ._session_data .get (" Scope" , [])
0 commit comments