Problem while using GmailAPI for adding auto-forwarding in account settings

Viewed 137

I wanted to use gmailAPI for my application to use the autoforwarding feature ,as i am new to the API i was following the steps given in the quickstart guide in python and i proceeded as follows

First i went to:- https://developers.google.com/gmail/api/quickstart/python?authuser=0 and followed all the steps over there to turn on gmail API and copy the credentials.JSON file to working directory and install the python package on the system and copied the code . Then i edited the scope to :- https://www.googleapis.com/auth/gmail.settings.sharing so that forwarding settings are available . Then I edited the code using :- https://developers.google.com/gmail/api/guides/forwarding_settings and the final code looks like this :-

import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

SCOPES = ['https://www.googleapis.com/auth/gmail.settings.sharing']

def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    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(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('gmail', 'v1', credentials=creds)
    address = { 'forwardingEmail': '<forwarding_mailid>' }
    result = service.users().settings().forwardingAddresses().\
        create(userId='me', body=address).execute()
    if result.get('verificationStatus') == 'accepted':
        body = {
            'emailAddress': result.get('forwardingEmail'),
            'enabled': True,
            'disposition': 'trash'
        }
        result = service.users().settings().\
            updateAutoForwarding(userId='me', body=body).execute()

if __name__ == '__main__':
    main()

It said that the forwading mail should also be verified so i verified "<forwarding_mailid>" in the account in forwarding setting in gmail (and i also tested it after removing mail id from the forwarding settings ) as said in :- https://developers.google.com/gmail/api/guides/forwarding_settings "You must create forwarding addresses prior to use. In some cases, users must also verify ownership of the address as well. If Gmail requires user verification for a forwarding address, the address is returned with the status pending. A verification message is automatically sent to the target email address. The owner of the email address must complete the verification process before it can be used. Forwarding addresses that do not require verification have a verification status of accepted."

Then i ran the script on the system then it asked to log in so i logged into account and then the script ran and console produced this error:-

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/settings/forwardingAddresses?alt=json returned "Access restricted to service accounts that have been delegated domain-wide authority">

the error was on this line :- "create(userId='me', body=address).execute()"

In every senario i got the same error at the same line i.e. while "result" generation. I am not able get what and where am i doing mistake or did i forgot some steps in between.

1 Answers

You need a service account with domain-wide authority:

As both the error you're getting and the updateAutoForwarding clearly state, you need to use a service account with domain-wide authority in order to update the auto-forwarding settings:

This method is only available to service account clients that have been delegated domain-wide authority.

Important: You need to be a domain administrator in order to grant domain-wide authority to a service account. So if you're not an admin, you cannot manage auto-forwarding through the API.

So you have to create a service account, grant it domain-wide authority, and use it to impersonate a regular account:

  • Check this for an overview of what service accounts are: specially this section for how to create them and this one for delegating domain-wide authority.

  • Once you have successfully set up the service account, you would have to change the way you're building the credentials in your code, to something like this:

creds = service_account.Credentials.from_service_account_file('credentials.json', scopes=SCOPES)
creds = creds.with_subject('impersonated_account@your_domain.com')

Where credentials.json is the downloaded JSON file for the service account, and impersonated_account@your_domain.com is the email address you want the service account to impersonate.

Reference:

Related