How do I get around HttpError 403 Insufficient Permission? (gmail API, Python)
Asked Answered
A

7

27

I keep getting the following error when I execute my code:

An error occurred: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/messages/send?alt=json returned "Insufficient Permission">

This is my code:

import httplib2
import os
from httplib2 import Http

from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

#SCOPES = 'https://www.googleapis.com/'
SCOPES = 'https://www.googleapis.com/auth/gmail.compose'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Gmail API Quickstart'

def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'gmail-quickstart.json')

    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatability with Python 2.6
            credentials = tools.run(flow, store)
        print 'Storing credentials to ' + credential_path
    return credentials

def CreateMessage(sender, to, subject, message_text):
  """Create a message for an email.

  Args:
    sender: Email address of the sender.
    to: Email address of the receiver.
    subject: The subject of the email message.
    message_text: The text of the email message.

  Returns:
    An object containing a base64 encoded email object.
  """
  message = MIMEText(message_text)
  message['to'] = to
  message['from'] = sender
  message['subject'] = subject
  return {'raw': base64.b64encode(message.as_string())}

testMessage = CreateMessage('ENTER SENDERS EMAIL ADDRESS', 'ENTER RECEIVERRS EMAIL ADDRESS', 'ENTER SUBJECT', 'ENTER EMAIL BODY')

def SendMessage(service, user_id, message):
  """Send an email message.

  Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    message: Message to be sent.

  Returns:
    Sent Message.
  """
  try:
    message = (service.users().messages().send(userId=user_id, body=message)
               .execute())
    print 'Message Id: %s' % message['id']
    return message
  except errors.HttpError, error:
    print 'An error occurred: %s' % error


testSend = SendMessage(service, 'me', testMessage)

I keep reading that I need to edit a credentials file, but I can't seem to find it. I have windows 7 installed. Does anyone know what I need to do in order to get past this error? I'm a totally new to this so please excuse me if I seem a bit new about this.

Afrikah answered 21/8, 2015 at 14:38 Comment(0)
D
22

Even though the accepted answer is 100% correct. I think it's worth pointing out that why that's the case.

When you authorize a gmail service client, you can specify several different scopes: All, compose, labels, etc...

These are all listed here: https://developers.google.com/gmail/api/auth/scopes

The scope mentioned in the answer provides complete gmail access.

Dildo answered 3/10, 2015 at 23:46 Comment(6)
github link is broken... :(Mcgough
yeah, github link is brokenAvalos
I found the scopes available here: developers.google.com/gmail/api/auth/scopesAvalos
fixed the link in the answerMertens
NOTE: For the NEW scope to take effect, you might need to delete the file at "~/.credentials/gmail-python-quickstart-.json" (as noted here: developers.google.com/gmail/api/quickstart/python )Efta
I had to delete the token.pickle file to be able to authorize the app again and make the changes in SCOPES have effectRetch
A
16

Solved it by changing the SCOPES line to:

SCOPES = 'https://mail.google.com/'

Email sending works perfectly

Afrikah answered 24/8, 2015 at 11:7 Comment(0)
A
11

Gmail API has these scopes: gmail api scopes

For sending emails, https://www.googleapis.com/auth/gmail.send is needed or full access https://mail.google.com/.

The scopes taken from here.

Avalos answered 15/5, 2016 at 6:18 Comment(0)
F
9

If you run the official "gmail-python-quickstart" before, please delete the file "gmail-quickstart.json" in your system. Rerun your program again so that you can set the priviledge as you want.

Feeley answered 4/7, 2016 at 5:52 Comment(0)
S
2

In Addition to the answers from:

  1. ccy
  2. apadana
  3. ragnampiza

and as a furtherance of ccy's answer...


Solution 1...

... a hack fix

If you're using the original gmail-python-quickstart code, make sure to also update the following:

  1. CLIENT_SECRET_FILE = '/path/to/your/secret_client.json'
  2. Force get_credentials() to use the failed credentials logic path...
if True:
    flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
    flow.user_agent = APPLICATION_NAME
    if flags:
        credentials = tools.run_flow(flow, store, flags)
    else: # Needed only for compatibility with Python 2.6
        credentials = tools.run(flow, store)
    print('Storing credentials to ' + credential_path)

to force True so that the logic operation will definitely work the client.flow operations:

if True:
    flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
    flow.user_agent = APPLICATION_NAME
    if flags:
        credentials = tools.run_flow(flow, store, flags)
    else: # Needed only for compatibility with Python 2.6
        credentials = tools.run(flow, store)
    print('Storing credentials to ' + credential_path)

This is a hacky fix, but will get you up and going in short time.

The Problem...

  • The problem with this approach is that it forces the flow code, which opens up the authentication window browser and requires that the end user accept the security protocol before sending the email.
  • This obviously breaks the concept of automated email generation and sending.

Solution 2...

...a stable, more automated solution

I found that doing the following works:

  1. Copy the downloaded the secret-client-####.html.json file to the directory defined in the first block of code from the get_credentials() method. Basically, copy it to your user/.credentials directory
  2. Delete the current gmail-python-quickstart.json
  3. Rename your downloaded file to gmail-python-quickstart.json

Run your code, and then it should work fine.

Benefits...

  • The authentication page does not show up
  • The email is sent automatically
Suannesuarez answered 29/12, 2016 at 6:24 Comment(0)
S
2

If you used google's official example, there should be a folder in ~/.credentials/ directory which is old, remove everything inside that directory and re-run your code. then you have to add new permissions and then everything is OK!

Silent answered 9/1, 2018 at 16:12 Comment(1)
this worked for me..it is clearly mentioned in developers.google.com/gmail/api/quickstart/javaVandyke
B
0

I had to do these steps:

  • copy my credentials.json to another file
  • delete credentials.json
  • re paste to the new credentials.json
  • rerun the app

to get it to work. Deleting token.json was not working for me.

Brianbriana answered 1/3 at 6:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.