Last active
February 26, 2021 23:30
-
-
Save piyueh/a2d65e095ea675a2c715ad42b7b61d10 to your computer and use it in GitHub Desktop.
Functions to get Google credentials & tokens for offlineimap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# vim:fenc=utf-8 | |
# | |
# Copyright © 2021 Pi-Yueh Chuang <[email protected]> | |
# | |
# Distributed under terms of the BSD 3-Clause license. | |
"""Functions used by an offlineimap instance. | |
Prerequisites: | |
* google-auth: https://google-auth.readthedocs.io | |
* google-auth-oauthlib: https://google-auth-oauthlib.readthedocs.io | |
""" | |
import pathlib | |
import pickle | |
import google.auth | |
import google_auth_oauthlib | |
def get_gmail_creds(account, client_credfile, scope=["https://mail.google.com/"]): | |
"""Get GMail account credential. | |
Arguments | |
--------- | |
account : str | |
Name of the account; used for naming the user credential file. | |
client_credfile : str or pathlike | |
Path to a JSON file that has client credentials. It can be created & downloaded from Google Cloud Console. | |
Returns | |
------- | |
A `google.oauth2.credentials.Credentials` instance. | |
""" | |
# process and save the absolute path of the credential file | |
client_credfile = pathlib.Path(client_credfile).expanduser() | |
if not client_credfile.is_absolute(): | |
client_credfile = pathlib.Path(__file__).parent.joinpath(client_credfile).expanduser() | |
client_credfile = client_credfile.resolve() | |
# token file contains pickled credentials of both the client and user-consented token | |
user_credfile = pathlib.Path(__file__).expanduser().resolve().parent.joinpath(account+".cred") | |
# try to see if the account's credential file exist; if so, read it | |
if user_credfile.exists(): | |
with open(user_credfile, "rb") as fobj: | |
user_creds = pickle.load(fobj) | |
# return the credential object | |
if user_creds.valid: | |
return user_creds | |
else: | |
user_creds = None | |
# user credentials exist but expired, just renew it if refresh token exists | |
if user_creds and user_creds.expired and user_creds.refresh_token: | |
user_creds.refresh(google.auth.transport.requests.Request()) | |
return user_creds | |
# user credentials does not exist or does not have a refresh token; open the browser for consent | |
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(client_credfile, scope) | |
user_creds = flow.run_local_server(port=59843) | |
with open(user_credfile, "wb") as fobj: | |
pickle.dump(user_creds, fobj) | |
return user_creds | |
def get_gmail_client_id(account, client_credfile): | |
"""Get the client id (in bytes) from credentials.""" | |
creds = get_gmail_creds(account, client_credfile) | |
return bytes(creds.client_id, "utf-8") # return `bytes` | |
# return creds.client_id # return `str` | |
def get_gmail_client_secret(account, client_credfile): | |
"""Get the client secret (in bytes) from credentials.""" | |
creds = get_gmail_creds(account, client_credfile) | |
return bytes(creds.client_secret, "utf-8") # return `bytes` | |
# return creds.client_secret # return `str` | |
def get_gmail_token(account, client_credfile): | |
"""Get the token (in bytes) from credentials.""" | |
creds = get_gmail_creds(account, client_credfile) | |
return bytes(creds.token, "utf-8") # return `bytes` | |
# return creds.token # return `str` | |
def get_gmail_refresh_token(account, client_credfile): | |
"""Get the refresh token (in bytes) from credentials.""" | |
creds = get_gmail_creds(account, client_credfile) | |
return bytes(creds.refresh_token, "utf-8") # return `bytes` | |
# return creds.refresh_token # return `str` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment