185 lines
6.6 KiB
Text
185 lines
6.6 KiB
Text
|
Python 3 update
|
||
|
https://patch-diff.githubusercontent.com/raw/google/gmail-oauth2-tools/pull/25.patch
|
||
|
|
||
|
Index: python/oauth2.py
|
||
|
--- python/oauth2.py.orig
|
||
|
+++ python/oauth2.py
|
||
|
@@ -60,15 +60,27 @@ IMAPFE and pass it as the second argument to the AUTHE
|
||
|
a AUTHENTICATE XOAUTH2 a9sha9sfs[...]9dfja929dk==
|
||
|
"""
|
||
|
|
||
|
+from __future__ import print_function
|
||
|
+
|
||
|
import base64
|
||
|
import imaplib
|
||
|
import json
|
||
|
from optparse import OptionParser
|
||
|
import smtplib
|
||
|
import sys
|
||
|
-import urllib
|
||
|
|
||
|
+try:
|
||
|
+ from urllib.request import urlopen
|
||
|
+ from urllib.parse import quote, unquote, urlencode
|
||
|
+except ImportError:
|
||
|
+ from urllib import urlopen, quote, unquote, urlencode
|
||
|
|
||
|
+if hasattr(__builtins__, 'raw_input'):
|
||
|
+ def input_str(prompt):
|
||
|
+ return raw_input(prompt).decode(sys.stdin.encoding)
|
||
|
+else:
|
||
|
+ input_str = input
|
||
|
+
|
||
|
def SetupOptionParser():
|
||
|
# Usage message is the module's docstring.
|
||
|
parser = OptionParser(usage=__doc__)
|
||
|
@@ -144,12 +156,12 @@ def AccountsUrl(command):
|
||
|
|
||
|
def UrlEscape(text):
|
||
|
# See OAUTH 5.1 for a definition of which characters need to be escaped.
|
||
|
- return urllib.quote(text, safe='~-._')
|
||
|
+ return quote(text, safe='~-._')
|
||
|
|
||
|
|
||
|
def UrlUnescape(text):
|
||
|
# See OAUTH 5.1 for a definition of which characters need to be escaped.
|
||
|
- return urllib.unquote(text)
|
||
|
+ return unquote(text)
|
||
|
|
||
|
|
||
|
def FormatUrlParams(params):
|
||
|
@@ -162,7 +174,7 @@ def FormatUrlParams(params):
|
||
|
A URL query string version of the given parameters.
|
||
|
"""
|
||
|
param_fragments = []
|
||
|
- for param in sorted(params.iteritems(), key=lambda x: x[0]):
|
||
|
+ for param in sorted(iter(params.items()), key=lambda x: x[0]):
|
||
|
param_fragments.append('%s=%s' % (param[0], UrlEscape(param[1])))
|
||
|
return '&'.join(param_fragments)
|
||
|
|
||
|
@@ -211,10 +223,12 @@ def AuthorizeTokens(client_id, client_secret, authoriz
|
||
|
params['grant_type'] = 'authorization_code'
|
||
|
request_url = AccountsUrl('o/oauth2/token')
|
||
|
|
||
|
- response = urllib.urlopen(request_url, urllib.urlencode(params)).read()
|
||
|
- return json.loads(response)
|
||
|
+ data = urlencode(params).encode('utf-8')
|
||
|
|
||
|
+ response = urlopen(request_url, data).read()
|
||
|
+ return json.loads(response.decode('utf-8'))
|
||
|
|
||
|
+
|
||
|
def RefreshToken(client_id, client_secret, refresh_token):
|
||
|
"""Obtains a new token given a refresh token.
|
||
|
|
||
|
@@ -235,10 +249,12 @@ def RefreshToken(client_id, client_secret, refresh_tok
|
||
|
params['grant_type'] = 'refresh_token'
|
||
|
request_url = AccountsUrl('o/oauth2/token')
|
||
|
|
||
|
- response = urllib.urlopen(request_url, urllib.urlencode(params)).read()
|
||
|
- return json.loads(response)
|
||
|
+ data = urlencode(params).encode('utf-8')
|
||
|
|
||
|
+ response = urlopen(request_url, data).read()
|
||
|
+ return json.loads(response.decode('utf-8'))
|
||
|
|
||
|
+
|
||
|
def GenerateOAuth2String(username, access_token, base64_encode=True):
|
||
|
"""Generates an IMAP OAuth2 authentication string.
|
||
|
|
||
|
@@ -254,7 +270,8 @@ def GenerateOAuth2String(username, access_token, base6
|
||
|
"""
|
||
|
auth_string = 'user=%s\1auth=Bearer %s\1\1' % (username, access_token)
|
||
|
if base64_encode:
|
||
|
- auth_string = base64.b64encode(auth_string)
|
||
|
+ auth_bytes = auth_string.encode('utf-8')
|
||
|
+ auth_string = base64.b64encode(auth_bytes).decode()
|
||
|
return auth_string
|
||
|
|
||
|
|
||
|
@@ -268,10 +285,11 @@ def TestImapAuthentication(user, auth_string):
|
||
|
auth_string: A valid OAuth2 string, as returned by GenerateOAuth2String.
|
||
|
Must not be base64-encoded, since imaplib does its own base64-encoding.
|
||
|
"""
|
||
|
- print
|
||
|
+ print()
|
||
|
+ auth_bytes = auth_string.encode('utf-8')
|
||
|
imap_conn = imaplib.IMAP4_SSL('imap.gmail.com')
|
||
|
imap_conn.debug = 4
|
||
|
- imap_conn.authenticate('XOAUTH2', lambda x: auth_string)
|
||
|
+ imap_conn.authenticate('XOAUTH2', lambda x: auth_bytes)
|
||
|
imap_conn.select('INBOX')
|
||
|
|
||
|
|
||
|
@@ -283,18 +301,19 @@ def TestSmtpAuthentication(user, auth_string):
|
||
|
auth_string: A valid OAuth2 string, not base64-encoded, as returned by
|
||
|
GenerateOAuth2String.
|
||
|
"""
|
||
|
- print
|
||
|
+ print()
|
||
|
+ auth_bytes = auth_string.encode('utf-8')
|
||
|
smtp_conn = smtplib.SMTP('smtp.gmail.com', 587)
|
||
|
smtp_conn.set_debuglevel(True)
|
||
|
smtp_conn.ehlo('test')
|
||
|
smtp_conn.starttls()
|
||
|
- smtp_conn.docmd('AUTH', 'XOAUTH2 ' + base64.b64encode(auth_string))
|
||
|
+ smtp_conn.docmd('AUTH', 'XOAUTH2 ' + base64.b64encode(auth_bytes).decode())
|
||
|
|
||
|
|
||
|
def RequireOptions(options, *args):
|
||
|
missing = [arg for arg in args if getattr(options, arg) is None]
|
||
|
if missing:
|
||
|
- print 'Missing options: %s' % ' '.join(missing)
|
||
|
+ print('Missing options: %s' % ' '.join(missing))
|
||
|
sys.exit(-1)
|
||
|
|
||
|
|
||
|
@@ -306,27 +325,27 @@ def main(argv):
|
||
|
response = RefreshToken(options.client_id, options.client_secret,
|
||
|
options.refresh_token)
|
||
|
if options.quiet:
|
||
|
- print response['access_token']
|
||
|
+ print(response['access_token'])
|
||
|
else:
|
||
|
- print 'Access Token: %s' % response['access_token']
|
||
|
- print 'Access Token Expiration Seconds: %s' % response['expires_in']
|
||
|
+ print('Access Token: %s' % response['access_token'])
|
||
|
+ print('Access Token Expiration Seconds: %s' % response['expires_in'])
|
||
|
elif options.generate_oauth2_string:
|
||
|
RequireOptions(options, 'user', 'access_token')
|
||
|
oauth2_string = GenerateOAuth2String(options.user, options.access_token)
|
||
|
if options.quiet:
|
||
|
- print oauth2_string
|
||
|
+ print(oauth2_string)
|
||
|
else:
|
||
|
- print 'OAuth2 argument:\n' + oauth2_string
|
||
|
+ print('OAuth2 argument:\n' + oauth2_string)
|
||
|
elif options.generate_oauth2_token:
|
||
|
RequireOptions(options, 'client_id', 'client_secret')
|
||
|
- print 'To authorize token, visit this url and follow the directions:'
|
||
|
- print ' %s' % GeneratePermissionUrl(options.client_id, options.scope)
|
||
|
- authorization_code = raw_input('Enter verification code: ')
|
||
|
+ print('To authorize token, visit this url and follow the directions:')
|
||
|
+ print(' %s' % GeneratePermissionUrl(options.client_id, options.scope))
|
||
|
+ authorization_code = input_str('Enter verification code: ')
|
||
|
response = AuthorizeTokens(options.client_id, options.client_secret,
|
||
|
authorization_code)
|
||
|
- print 'Refresh Token: %s' % response['refresh_token']
|
||
|
- print 'Access Token: %s' % response['access_token']
|
||
|
- print 'Access Token Expiration Seconds: %s' % response['expires_in']
|
||
|
+ print('Refresh Token: %s' % response['refresh_token'])
|
||
|
+ print('Access Token: %s' % response['access_token'])
|
||
|
+ print('Access Token Expiration Seconds: %s' % response['expires_in'])
|
||
|
elif options.test_imap_authentication:
|
||
|
RequireOptions(options, 'user', 'access_token')
|
||
|
TestImapAuthentication(options.user,
|
||
|
@@ -339,7 +358,7 @@ def main(argv):
|
||
|
base64_encode=False))
|
||
|
else:
|
||
|
options_parser.print_help()
|
||
|
- print 'Nothing to do, exiting.'
|
||
|
+ print('Nothing to do, exiting.')
|
||
|
return
|
||
|
|
||
|
|