HttpError 400 Bad Request - Google Admin Directory API (Python) - python

I'm having difficulty creating a Google Project as a Service Account. I am using the Admin SDK in Python, specifically the Directory API. I believe I am authenticating correctly but when it comes to calling users.list I get the following error:
Traceback (most recent call last):
File "googleproject.py", line 17, in <module>
userlist = service.users().list().execute(http = http_auth)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 135, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 723, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/admin/directory/v1/users?alt=json returned "Bad Request">
My code is as follows:
from oauth2client.client import SignedJwtAssertionCredentials
from httplib2 import Http
from apiclient.discovery import build
#----AUTHORISATION----#
client_email = '*****#developer.gserviceaccount.com'
with open('*****.p12') as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, 'https://www.googleapis.com/auth/admin.directory.user')
http_auth = credentials.authorize(Http())
#--------------------#
service = build('admin', 'directory_v1', http = http_auth)
userlist = service.users().list().execute(http = http_auth)
I have tried it with and without passing http = http_auth as an argument to execute(). I've basically followed the example given here: https://code.google.com/p/google-api-python-client/source/browse/samples/service_account/tasks.py
I have enabled Admin SDK in the Developers console, as well as added the client id and scope in the Google Apps control panel.

I managed to fix it! The problem was I wasn't setting the domain in the list argument. So the new code is as follows:
from oauth2client.client import SignedJwtAssertionCredentials
from httplib2 import Http
from apiclient.discovery import build
#----AUTHORISATION----#
client_email = '*****#developer.gserviceaccount.com'
with open('*****') as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, 'https://www.googleapis.com/auth/admin.directory.user', sub = 'super-admin#domain.com')
http_auth = credentials.authorize(Http())
#--------------------#
service = build('admin', 'directory_v1', http = http_auth)
user = service.users().list(showDeleted = False, domain = 'domain.com').execute()

Related

Google contact API raise TypeError('Got an unexpected keyword argument "%s"' % name)

I try my google API Project
from __future__ import print_function
import httplib2
from oauth2client import tools
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from apiclient import discovery
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# Set up a Flow object to be used if we need to authenticate. This
# sample uses OAuth 2.0, and we set up the OAuth2WebServerFlow with
# the information it needs to authenticate. Note that it is called
# the Web Server Flow, but it can also handle the flow for
# installed applications.
#
# Go to the Google API Console, open your application's
# credentials page, and copy the client ID and client secret.
# Then paste them into the following code.
FLOW = OAuth2WebServerFlow(
client_id='592262365202-h6qu4mrf2b043e2gv2qf5grjg0j53ádfasdfsf2s5.apps.googleusercontent.com',
client_secret='VVxrBm9SEádfsf1ONzyX1oIEwSfB2',
scope='https://www.googleapis.com/auth/contacts',
user_agent='contact_cms/YOUR_APPLICATION_VERSION')
# If the Credentials don't exist or are invalid, run through the
# installed application flow. The Storage object will ensure that,
# if successful, the good Credentials will get written back to a
# file.
def get_credentials(FLOW):
storage = Storage('info.dat')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
credentials = tools.run_flow(FLOW, storage)
return credentials
# Create an httplib2.Http object to handle our HTTP requests and
# authorize it with our good Credentials.
def get_http(credentials):
http = httplib2.Http()
http = credentials.authorize(http)
return http
# Build a service object for interacting with the API. To get an API key for
# your application, visit the Google API Console
# and look at your application's credentials page.
def print_list_google_contact_with_number_of_contacts(creds, numberofcontact):
# Call the People API
service = build('people', 'v1', credentials=creds)
print('Ban dang in ra ', numberofcontact, ' danh ba')
results = service.people().connections().list(
resourceName='people/me',
pageSize=numberofcontact,
personFields='names,emailAddresses,phoneNumbers,emailAddresses,addresses').execute()
connections = results.get('connections', [])
# for person in connections:
# names = person.get('names', [])
# if names:
# name = names[0].get('displayName')
# print(name)
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
else:
name = None
phoneNumbers = person.get('phoneNumbers', [])
if phoneNumbers:
phoneNumber = phoneNumbers[0].get('value')
else:
phoneNumber = None
Cities = person.get('addresses', [])
if Cities:
City = Cities[0].get('city')
else:
City = None
emails = person.get('emailAddresses', [])
if emails:
email = emails[0].get('value')
else:
email = None
print(f'{name}: {phoneNumber}: {City}: {email}')
def creat_a_google_contact(http):
service = discovery.build('people', 'v1', http=http, discoveryServiceUrl='https://people.googleapis.com/$discovery/rest')
service.people().createContact(parent='people/me', body={
"names": [
{
'givenName': "Samkafafsafsafit"
}
],
"phoneNumbers": [
{
'value': "8600086024"
}
],
"emailAddresses": [
{
'value': "samkit5495#gmail.com"
}
]
}).execute()
def main():
creds=get_credentials(FLOW)
http=get_http(creds)
printout=print_list_google_contact_with_number_of_contacts(creds,10)
creat_a_google_contact(http)
return print(printout)
if __name__ == '__main__':
main()
But when i run, have the log
Traceback (most recent call last):
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 116, in <module>
main()
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 113, in main
creat_a_google_contact(http)
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 104, in creat_a_google_contact
'value': "samkit5495#gmail.com"
File "/Users/nguyenngoclinh/.conda/envs/1z_vietnam/lib/python3.7/site-packages/googleapiclient/discovery.py", line 840, in method
raise TypeError('Got an unexpected keyword argument "%s"' % name)
TypeError: Got an unexpected keyword argument "parent"
createContact() does not have a parent param. It has been deprecated:
https://developers.google.com/people/api/rest/v1/people/createContact
parent='people/me' is deprecated. Try without that.

GMAIL API:forward all the client gmail messages to a gmail address by using gmail api

Currently, I am writing a program to forward all the Gmail messages of users to a Gmail address
I took the help from:Link
I created all the storage, credentials file etc
but when I try to run the program it's giving an error:
Traceback (most recent call last):
File "hh.py", line 40, in <module>
thadari()
File "hh.py", line 30, in thadari
result = GMAIL.users().settings().forwardingAddresses().create(userId='me', body=address).execute()
File "/home/vishalthadari/Documents/Seperation 1/virutalenv/python 3/env/lib/python3.6/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/vishalthadari/Documents/Seperation 1/virutalenv/python 3/env/lib/python3.6/site-packages/googleapiclient/http.py", line 842, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/settings/forwardingAddresses?alt=json returned "Insufficient Permission">
i already gave the sending mail permission to it but I don't know why it's giving the error.there's no scope for forward message as I read here:link
Or do I need to buy google gsuite for this? which is defined here:Link
in gmail.settings.sharing
I know that whole wall of code is not reusable but as I am new to Google API's so I think their's small minor bugs in 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 re
import time
import dateutil.parser as parser
from datetime import datetime
import datetime
import csv
def thadari():
SCOPES = 'https://www.googleapis.com/auth/gmail.send'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
GMAIL = discovery.build('gmail', 'v1', http=creds.authorize(Http()))
user_id = 'me'
label_id_one = 'INBOX'
address = {'forwardingEmail': 'girlsdontloveme75#gmail.com'}
result = GMAIL.users().settings().forwardingAddresses().create(userId='me', body=address).execute()
if result.get('verificationStatus') == 'accepted':
body = {
'emailAddress': result.get('forwardingEmail'),
'enabled': True,
'disposition': 'trash'
}
if __name__ == '__main__':
thadari()
Is this the right way to do it? or there's a better way to do this please help me
Thanks in advance

Writing in Google Sheets API v4 using Python

I have been trying really hard to do my code working just by reading examples, but i can't find an example about the correct way of writting in a sheet using the API.
Here's the part of my code that it isn't working:
def comprar(producto,cantidad):
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
'version=v4')
service = discovery.build('sheets', 'v4', http=http,
discoveryServiceUrl=discoveryUrl)
spreadsheetId = '1oN1WkdXSYIlsgjFKZX1YolwajNflqAgE20w8vcRaY8Y'
row = searchInCol("A",producto)
target = "Inventario!"+"J"+str(row)
values = [
[
# Cell values to be inputed...
int(cantidad)
],
# Additional rows ...
]
body = {"values":values}
print("Entra")
#THIS ISN'T WOKRING
result = service.spreadsheets().values().update(
spreadsheetId=spreadsheetId, range=target,
valueInputOption="USER_ENTERED", body=body).execute()
print("entra")
The function that is not working is the comprar one, the console says: "Request had insufficient authentication scopes". I can't even understand what it means.
By the way here you have the function get_credentials():
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,
'sheets.googleapis.com-python-quickstart.json')
store = 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 compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
And here I have all the modules imported:
from __future__ import print_function
import httplib2
import os
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
import time
If anyone could explain me a little bit of what's wrong and an example of a working code for writing in a google sheet using python and the API, it would be really helpful. And also, if you need any more information about the code, please tell me. (I'm just a noob student.)
Edit:
I've changed this:
SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
To this:
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
But it keeps throwing the following error:
Traceback (most recent call last):
File "quickstart.py", line 210, in <module>
comprar(pro,cnt)
File "quickstart.py", line 196, in comprar
valueInputOption="USER_ENTERED", body=body).execute()
File "/usr/local/lib/python2.7/dist-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 838, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://sheets.googleapis.com/v4/spreadsheets/1oN1WkdXSYIlsgjFKZX1YolwajNflqAgE20w8vcRaY8Y/values/Inventario%21J1?alt=json&valueInputOption=USER_ENTERED returned "Request had insufficient authentication scopes.">
Thanks!
Well, make sure that you enable all the API that you used here especially the Sheets API in your Developers Console.
The error "Request had insufficient authentication scopes" that you receive is an error in the OAuth 2.0 token provided in the request that specify the scopes that you are using are insufficient for accessing the requested data.
So make sure you follow the steps here on this documentation on how to Authorize your request with OAuth.
For more information, you can check this related SO question.

Error 403 when trying to upload file to google drive via python

So I'm new to python (and this is a first post to stack overflow). I'm trying to use python to upload and download files to and from a google drive account (and eventually reference files from this drive on a customized work tiki wiki). The code below is from google's python api resources. It will successfully list the files on my drive (as it should). However, when I attempt to upload a file (see 10th line from bottom) I am given the following error:
An error occured: <HttpError 403 "Insufficient Permission">
I've been looking around for a few hours now and I can't figure out how to get around this. I'm thinking I need to request some sort of token. Not really sure. Again, I'm new to this. Any help would be greatly appreciated!
import httplib2
import os
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/auth/drive.metadata.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive 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,
'drive-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
from apiclient import errors
from apiclient.http import MediaFileUpload
# ...
def insert_file(service, title, description, parent_id, mime_type, filename):
"""Insert new file.
Args:
service: Drive API service instance.
title: Title of the file to insert, including the extension.
description: Description of the file to insert.
parent_id: Parent folder's ID.
mime_type: MIME type of the file to insert.
filename: Filename of the file to insert.
Returns:
Inserted file metadata if successful, None otherwise.
"""
media_body = MediaFileUpload(filename, mimetype=mime_type, resumable=True)
body = {
'title': title,
'description': description,
'mimeType': mime_type
}
# Set the parent folder.
if parent_id:
body['parents'] = [{'id': parent_id}]
try:
file = service.files().insert(
body=body,
media_body=media_body).execute()
# Uncomment the following line to print the File ID
# print 'File ID: %s' % file['id']
return file
except errors.HttpError, error:
print 'An error occured: %s' % error
return None
def main():
"""Shows basic usage of the Google Drive API.
Creates a Google Drive API service object and outputs the names and IDs
for up to 10 files.
"""
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v2', http=http)
insert_file(service, 'picture.jpg', 'no_description', False, 'image/jpeg', '/Users/ethankay/Documents/Work/Current_Work/Astrophysics/Code/Logger_Program/Master/TestUploadFiles/test3.jpg')
results = service.files().list(maxResults=10).execute()
items = results.get('items', [])
if not items:
print 'No files found.'
else:
print 'Files:'
for item in items:
print '{0} ({1})'.format(item['title'], item['id'])
if __name__ == '__main__':
main()
your Google Drive scope is
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
which has no permission to upload files. You need to change it to
SCOPES = 'https://www.googleapis.com/auth/drive'
to be able to manage files. Try to re-authenticate with your Google API project.
Save this code as quickstart.py
Run it from command line using sudo. [ sudo python quickstart.py ]
Use your Windows Password
The quickstart.py will attempt to open a new window or tab in your default browser. If this fails, copy the URL from the console and manually open it in your browser.
Click the Accept button
DONE

gmail api http connection fails for properly configured service account with delegated domain access

I'm trying to get a connection to my gmail inbox via the python API.
I've got a working example for connecting to the directory api to do user maintenance operations that is set up and working nearly identically to this code. So I've been through all the dev console and security setup for my service account user, who has an email box with a test email sitting in it waiting for me to read it with this code. Currently, my issue is that the line:
gmail_service = build('gmail', 'v1', http=http)
throws:
File "./gmail_test.py", line 29, in <module>
gmail_service = build('gmail', 'v1', http=http)
NameError: name 'http' is not defined
Not quite sure what I'm missing as the nearly identical tailored for admin sdk access works great.
anyway, here's the code:
import urllib2
from httplib2 import Http
from googleapiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
client_email = '<private>#developer.gserviceaccount.com'
with open("Unsubscribe Processing.p12") as f:
private_key = f.read()
creds = SignedJwtAssertionCredentials(
client_email,
private_key,
{
'https://www.googleapis.com/auth/gmail.readonly'
},
sub='serviceaccount#ourdomain.com')
auth = creds.authorize(Http())
gmail_service = build('gmail', 'v1', http=http)
results = gmail_service.users().labels().list(userId='serviceaccount#ourdomain.com').execute()
labels = results.get('labels', [])
if not labels:
print 'No labels found.'
else:
print 'Labels:'
for label in labels:
print label['name']
if __name__ == '__main__':
main()
You haven't defined what the variable http is.
From https://developers.google.com/gmail/api/auth/web-server, this seems to be how you create a Gmail service object:
http = httplib2.Http()
http = creds.authorize(http)
gmail_service = build('gmail', 'v1', http=http)

Categories

Resources