Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gmail API returns 403 error code and “Delegation denied for <user email> #80

Closed
dapsjj opened this issue Feb 19, 2019 · 1 comment
Closed
Assignees

Comments

@dapsjj
Copy link

dapsjj commented Feb 19, 2019

I run my code with administrative privileges.
My code:

from apiclient import discovery
from apiclient import errors
from httplib2 import Http
from oauth2client import file, client, tools
import base64
from bs4 import BeautifulSoup
import dateutil.parser as parser

# Creating a storage.JSON file with authentication details
SCOPES = 'https://www.googleapis.com/auth/gmail.modify'  # we are using modify and not readonly, as we will be marking the messages Read
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('Administrator_Gmail.json', SCOPES)
    creds = tools.run_flow(flow, store)
GMAIL = discovery.build('gmail', 'v1', http=creds.authorize(Http()))

user_id = 'greatXXX@XXX.XXX'
label_id_one = 'INBOX'
label_id_two = 'UNREAD'

unread_msgs = GMAIL.users().messages().list(userId=user_id, maxResults=10).execute()

# We get a dictonary. Now reading values for the key 'messages'
mssg_list = unread_msgs['messages']

print("Total unread messages in inbox: ", str(len(mssg_list)))

final_list = []

for mssg in mssg_list:
    temp_dict = {}
    m_id = mssg['id']  # get id of individual message
    message = GMAIL.users().messages().get(userId=user_id, id=m_id).execute()  # fetch the message using API
    payld = message['payload']  # get payload of the message
    headr = payld['headers']  # get header of the payload

    for one in headr:  # getting the Subject
        if one['name'] == 'Subject':
            msg_subject = one['value']
            temp_dict['Subject'] = msg_subject
        else:
            pass

    for two in headr:  # getting the date
        if two['name'] == 'Date':
            msg_date = two['value']
            date_parse = (parser.parse(msg_date))
            m_date = (date_parse.date())
            temp_dict['Date'] = str(m_date)
        else:
            pass

    for three in headr:  # getting the Sender
        if three['name'] == 'From':
            msg_from = three['value']
            temp_dict['Sender'] = msg_from
        else:
            pass

    temp_dict['Snippet'] = message['snippet']  # fetching message snippet

    try:

        # Fetching message body
        mssg_parts = payld['parts']  # fetching the message parts
        part_one = mssg_parts[0]  # fetching first element of the part
        part_body = part_one['body']  # fetching body of the message
        part_data = part_body['data']  # fetching data from the body
        clean_one = part_data.replace("-", "+")  # decoding from Base64 to UTF-8
        clean_one = clean_one.replace("_", "/")  # decoding from Base64 to UTF-8
        clean_two = base64.b64decode(bytes(clean_one, 'UTF-8'))  # decoding from Base64 to UTF-8
        soup = BeautifulSoup(clean_two, "lxml")
        mssg_body = soup.body()
        temp_dict['Message_body'] = mssg_body
    except:
        pass
    print(temp_dict)
    final_list.append(temp_dict)  # This will create a dictonary item in the final list
    # This will mark the messagea as read
    # GMAIL.users().messages().modify(userId=user_id, id=m_id, body={'removeLabelIds': ['UNREAD']}).execute()
print("Total messaged retrived: ", str(len(final_list)))

When I replaced userId with an employee's gmail in my company,the error message is:

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/aXXXXXX/messages?maxResults=10&alt=json returned "Delegation denied for XXX.XXX.XXX">

Where is wrong?

@sqrrrl sqrrrl self-assigned this Feb 19, 2019
@sqrrrl
Copy link
Member

sqrrrl commented Feb 19, 2019

The gmail docs are a little sparse here, but the guide for managing delegates links to https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority which explains what you need to do to get this to work.

From the code, it looks like you're using the web/installed app end-user flows for oauth, and just authorizing with an admin account. That produces a token to access the admin's gmail account, but the fact that the user is an admin doesn't grant it any additional privileges.

Instead, you need to create a service account and grant it access to impersonate users on the domain in order to do what you're trying to do.

I know it's a bit weird to jump through the extra hoops, but the extra restrictions are in place to prevent abuse of delegation/forwarding rules by malicious apps since they persist independent of the OAuth authorization.

@sqrrrl sqrrrl closed this as completed Feb 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants