python-3.xgoogle-cloud-platformgmail-apiapi-authorization

Gmail Api Automatic Authentication Flow Problem


Is there any way to send an email with Gmail Api with automatic authentication? If we have not this option then we have to choose the authentication account manually. Actually this is not desired situation. The statement appears on Google tab which opens automatically after manually steps are done:

The authentication flow has completed. You may close this window.

After this message and authentication, the code is sending the email to the desired account.

Example code:
from google.oauth2.credentials import Credentials

# Check if there is a valid token.pickle file
creds = None
if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = Credentials.from_authorized_user_file(token, SCOPES)

# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
        creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open('token.pickle', 'wb') as token:
        pickle.dump(creds, token)

Solution

  • Presumably, your code is to run inside the cloud (cloud run? cloud function?, etc.), so it is executed under some (preferably some specific, dedicated, with relevant minimum IAM permissions) service account.

    You probably would like to delegate domain wide authority to that service account.

    Details are here: Set up domain-wide delegation for a service account, here: Control API access with domain-wide delegation and here: Delegating domain-wide authority to the service account

    Here is a Stack Overflow answer which described this approach in python: Gmail API service account unauthorized_client error even with domain-wide authority - how to get access to the gmail account without any private keys from inside a cloud function.

    Fingers cross, the code snippet in that answer is still correct.