I am trying to download a spreadsheet file from my drive to my computer.
I am able to authenticate, get list of files and even get meta-data successfully.
But when I try to download the file, I get the following error :
downloading file starts
An error occurred: <HttpError 400 when requesting https://www.googleapis.com/dri
ve/v2/files/1vJetI_p8YEYiKvPVl0LtXGS5uIAx1eRGUupsXoh7UbI?alt=media returned "The
specified file does not support the requested alternate representation.">
downloading file ends
I couldn't get any such problem or question on SO and the other methods or solutions provided on SO for downloading the spreadsheet are outdated.Those have been deprecated by Google .
Here is the code, I am using to download the file :
import httplib2
import os
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
from apiclient import errors
from apiclient import http
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
#SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secrets.json'
APPLICATION_NAME = 'Drive API Quickstart'
def get_credentials():
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
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v2', http=http)
file_id = '1vJetI_p8YEYiKvPVl0LtXGS5uIAx1eRGUupsXoh7UbI'
print "downloading file starts"
download_file(service, file_id)
print "downloading file ends "
def download_file(service, file_id):
local_fd = open("foo.csv", "w+")
request = service.files().get_media(fileId=file_id)
media_request = http.MediaIoBaseDownload(local_fd, request)
while True:
try:
download_progress, done = media_request.next_chunk()
except errors.HttpError, error:
print 'An error occurred: %s' % error
return
if download_progress:
print 'Download Progress: %d%%' % int(download_progress.progress() * 100)
if done:
print 'Download Complete'
return
if __name__ == '__main__':
main()
Google spreadsheets don't have media. Instead they have exportLinks. Get the file metadata, then look in the exportlinks and pick an appropriate URL.
This code worked for me. I only had to download client_secret.json from google developers dashboard and keep in the same directory as python script.
And in the list_of_lists variable I got a list with each row as list.
import gspread
import json
from oauth2client.client import SignedJwtAssertionCredentials
json_key = json.load(open('client_secret.json'))
scope = ['https://spreadsheets.google.com/feeds']
credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'], scope)
gc = gspread.authorize(credentials)
sht1 = gc.open_by_key('<id_of_sheet>')
worksheet_list = sht1.worksheets()
worksheet = sht1.sheet1
list_of_lists = worksheet.get_all_values()
for row in list_of_lists :
print row
Related
I have pretty similar code as google on a quick start page suggest.
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
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Google Sheets API Python 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,
'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
def main():
"""Shows basic usage of the Sheets API.
Creates a Sheets API service object and prints the names and majors of
students in a sample spreadsheet:
https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
"""
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 = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'
rangeName = 'Class Data!A2:E'
result = service.spreadsheets().values().get(
spreadsheetId=spreadsheetId, range=rangeName).execute()
values = result.get('values', [])
if not values:
print('No data found.')
else:
print('Name, Major:')
for row in values:
# Print columns A and E, which correspond to indices 0 and 4.
print('%s, %s' % (row[0], row[4]))
if __name__ == '__main__':
main()
Firstly, I created my own secret file. Then executed without that file 'sheets.googleapis.com-python-quickstart.json' and .credentials folder was created, but faced sheets.googleapis.com-python-quickstart.json: No such file or directory error
So then I created that empty file sheets.googleapis.com-python-quickstart.json on that folder, but faced another error KeyError: '_module'. I even tried to rename my secret file as sheets.googleapis.com-python-quickstart.json - same error. I have executed this code from console and from ipython notebook - same error. Changing SCOPES by deleting .readonly - didn't help
Is there any webpage should be opened? What am I doing wrong?
My question looks the same as - but nothing helped and my question should be about a bit different think
Full error stack:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-83-58ca95c5b364> in <module>()
----> 1 main()
<ipython-input-82-1e078df2aa91> in main()
37 https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
38 """
---> 39 credentials = get_credentials()
40 http = credentials.authorize(httplib2.Http())
41 discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
<ipython-input-82-1e078df2aa91> in get_credentials()
20
21 store = Storage(credential_path)
---> 22 credentials = store.get()
23
24 if not credentials or credentials.invalid:
~\AppData\Local\Continuum\Anaconda3\lib\site-packages\oauth2client\client.py in get(self)
405 self.acquire_lock()
406 try:
--> 407 return self.locked_get()
408 finally:
409 self.release_lock()
~\AppData\Local\Continuum\Anaconda3\lib\site-packages\oauth2client\file.py in locked_get(self)
52
53 try:
---> 54 credentials = client.Credentials.new_from_json(content)
55 credentials.set_store(self)
56 except ValueError:
~\AppData\Local\Continuum\Anaconda3\lib\site-packages\oauth2client\client.py in new_from_json(cls, json_data)
300 # Find and call the right classmethod from_json() to restore
301 # the object.
--> 302 module_name = data['_module']
303 try:
304 module_obj = __import__(module_name)
KeyError: '_module'
First of all proper JSON should be downloaded, it should be for web server.
Secondly that JSON should contain redirect URL "redirect_uris":"http://localhost:8080/"
That URL also should be added to settings in the google account, where you have just generated that JSON
I have a python script to match files on google drive in specific folder. It worked fine with my GSuite account in the company. But If i want to use it at home with my simple Google Drive account it's not working. No files found:
Here is my code:
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from apiclient.http import MediaFileUpload
from apiclient import errors
import io
from apiclient.http import MediaIoBaseDownload
from apiclient import errors
import os
import csv
try :
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
folder_id = 'XYZ00000'
SCOPES = 'https://www.googleapis.com/auth/drive.file'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
print("Create new data storage file ...")
flow = client.flow_from_clientsecrets('client_secrets.json', SCOPES)
flow.redirect_uri = client.OOB_CALLBACK_URN
authorize_url = flow.step1_get_authorize_url()
creds = tools.run_flow(flow, store, flags) \
if flags else tools.run(flow, store)
print ("Storage")
DRIVE = build('drive', 'v2', http=creds.authorize(Http()))
def getKeywordsID():
page_token = None
while True:
response = DRIVE.files().list(q="'XYZ00000' in parents and trashed = false",
spaces='drive',
fields='nextPageToken, items(id, title)',
pageToken=page_token).execute()
for file in response.get('items', []):
if ('test.txt' == file.get('title')):
print ('test.txt on Google Drive found')
page_token = response.get('nextPageToken', None)
if page_token is None:
break;
return file_id
# Download file
file_id = getKeywordsID()
if file_id != None:
request = DRIVE.files().get_media(fileId=file_id)
fh = io.FileIO('test.txt', 'wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ("Download test.txt %d%%." % int(status.progress() * 100) )
else:
print ("File not found.")
I have no idea why it's not working. I enabled Google Drive API, created a project, added an OAuth2.0 client ID (select “Other” as option) and downloaded the json file for storage.
From the traceback posted, I can see that in the getKeywordsID function you are returning the file_id variable, which you have not initialized in the getKeywordsID function scope. Hence the UnboundLocalError: local variable 'file_id' referenced before assignment is thrown.
My goal is to have a list of all of the items & folders in everyone's Google Drive. I'm starting with trying to make sure the script works on my own. I have read cover-to-cover the Drive REST API documentation, and eventually found this code, which can also be found here.
from __future__ import print_function
import httplib2
import os
import sys
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
reload(sys)
sys.setdefaultencoding('utf-8')
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/drive-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive API Python 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-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
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', 'v3', http=http)
results = service.files().list(
pageSize=1000,fields="nextPageToken, files(mimeType, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['mimeType']))
if __name__ == '__main__':
main()
My problem is with the nextPageToken, and how to properly use it. The max PageSize is 1000, so I must loop over the nextPageToken, fetch it from the resulting JSON, put it back into the original loop (line 66?), to get another 1000 results. How do I do this?
Let's look the google drive api documentation for the File:list Method
In the fields of your request you are asking the nextPageToken, the result will contain the token for the nextPage (if the nextPage exists).
The result will be something like this :
{
...,
"nextPageToken": "V1*3|0|XXXXXX",
"files": [
{
...
},...
]
}
you can extract nextPageToken value like :
token = results.get('nextPageToken', None)
The List method can take the string parameter pageToken :
The token for continuing a previous list request on the next page.
This should be set to the value of 'nextPageToken' from the previous
response.
Just set the parameter pageToken in the next request to get the next page of results :
results = service.files().list(
pageSize=1000,
pageToken=token,
fields="nextPageToken, files(mimeType, name)").execute()
items = results.get('files', [])
Now you can easily make a loop to get all result.
I will try to demonstrate the concept for you but you'll do the implementation in Python. The short answer is, nextPageToken. nextPageTokens enable you to retrieve the results from the next page.
When you perform a GET request, a nextPageToken will always be included in the response so if you had 1000 results but you only wanted to display 20 per page, you can fetch the remaining 980 files using nextPageToken.
Run this URL and you'll see something like:
"kind": "drive#fileList",
"nextPageToken": "V1*3|0|CjkxOHY2aDdROE9JYkJGWUJEaU5Ybm1OVURSemJTcWFMa2lRQlVJSnVxYmI2YkYzMmhnVHozeWkwRnASBxCqqcG4kis",
"incompleteSearch": false,
The value of the nextPageToken here is what you use to get to the next page. When you get to the next page and you have more results, a new nextPageToken will be generated for you until you view/get all the results (980-1000).
You must looping while token (for the nextpage) is not null, like this code at the end:
(do not forget to install -->
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
Copy and paste this code (Do not forget to change your paths and your googleDrive folder ID, at the end)
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
# If modifying these scopes, delete the file token.pickle.
SCOPES = [
'https://www.googleapis.com/auth/spreadsheets',
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive"
]
# FOR AUTHENTICATION
def authenticate():
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(
'YOUR PATH FOR THE CREDENTIALS JSON/credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('YOUR PATH /token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
return service
# LISTS TO TAKE ALL FILES AND IDs FROM SPECIFIC FOLDER
listFilesDrive=[]
line = []
# TO TAKE ALL FILES FROM SPECIFIC FOLDER
def listFilesFromGoogleFolder(IDFolder):
service = authenticate()
# Call the Drive v3 API
results = service.files().list( q="'{}' in parents".format(FolderIDFromGDrive),
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
# TAKE TOKEN FROM THE NEXT PAGE (IF THERE IS NO ONE, THIS VALUE WILL BE NULL)
token = results.get('nextPageToken', None)
#print('token->>',nextPageToken)
if not items:
print('No files found.')
else:
print('Files:')
line = []
for item in items:
# TAKE FIRST PAGE IN A LIST ->> "listFilesDrive"
arquivo = item['name']
IDarquivo = item['id']
line.append(arquivo)
line.append(IDarquivo)
listFilesDrive.append(line)
line=[]
print(u'{0} ({1})'.format(item['name'], item['id']))
# LOOPING WHILE TOKEN FOR OTHER PAGES IS NOT NULL TOKEN
while token!=None:
service = authenticate()
results = service.files().list( q="'{}' in parents".format(IDFolder),
pageToken=token,
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
# TAKE A NEW TOKEN FOR THE NEXT PAGE, IF THERE IS NO, THIS TOKEN WILL BE NULL ("None")
token = results.get('nextPageToken', None)
if not items:
print('No files found.')
else:
print('Files:')
linha = []
for item in items:
arquivo = item['name']
IDarquivo = item['id']
line.append(arquivo)
line.append(IDarquivo)
listFilesDrive.append(line)
line=[]
print(u'{0} ({1})'.format(item['name'], item['id']))
print(len(listFilesDrive))
print(listFilesDrive)
# put your specific information
if __name__ == '__main__':
FolderIDFromGDrive='YOUR FOLDER ID'
listFilesFromGoogleFolder(FolderIDFromGDrive)
I had quite a bit of trouble with this. I didn't read the example closely enough to notice that nextPageToken & newStartPageToken were not the same thing.
I split up the functions a little and added a loop. Basically, return the startPageToken and loop over the same function / call the function as required.
from __future__ import print_function
import httplib2
import os
#julian
import time
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/drive-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive API Python 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-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
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', 'v3', http=http)
saved_start_page_token = StartPage_v3(service)
saved_start_page_token = DetectChanges_v3(service, saved_start_page_token)
starttime=time.time()
while True:
saved_start_page_token = DetectChanges_v3(service, saved_start_page_token)
time.sleep(10.0 - ((time.time() - starttime) % 10.0))
def StartPage_v3(service):
response = service.changes().getStartPageToken().execute()
print('Start token: %s' % response.get('startPageToken'))
return response.get('startPageToken')
def DetectChanges_v3(service, saved_start_page_token):
# Begin with our last saved start token for this user or the
# current token from getStartPageToken()
page_token = saved_start_page_token;
while page_token is not None:
response = service.changes().list(pageToken=page_token, spaces='drive').execute()
for change in response.get('changes'):
# Process change
mimeType = change.get('file').get('mimeType')
print( 'Change found for: %s' % change)
if 'newStartPageToken' in response:
# Last page, save this token for the next polling interval
saved_start_page_token = response.get('newStartPageToken')
page_token = response.get('nextPageToken')
return saved_start_page_token
if __name__ == '__main__':
main()
In python how do i mark messages as 'read' as i parse it from gmail api ?
Also how do i save the values to the database after parsing?
This is the code so far to get the content of each message.
from __future__ import print_function
import httplib2
import os
import re
import MySQLdb
from email.utils import parsedate_tz,mktime_tz,formatdate
from requests.adapters import HTTPAdapter
import datetime
from datetime import date,timedelta
import time
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
import json
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
CLIENT_SECRET_FILE = 'client_server.json'
APPLICATION_NAME = 'Gmail API Python Quickstart'
def get_credentials():
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-python-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 compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
da=date.fromordinal(730920)
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
today=date.today()
print (today)
yesterday=today-timedelta(1)
print (yesterday)
response = service.users().messages().list(userId='me',q='in:inbox is:unread newer_than:1d').execute()
messages=[]
store=[]
message1=[]
test2=[]
da=[]
if 'messages' in response:
messages.extend(response['messages'])
fo = open("fooa.txt", "wb")
for i in range(len(messages)):
store=messages[i]['id']
message = service.users().messages().get(userId='me',id=store,format='metadata',metadataHeaders=['from','date']).execute()
fo.write(message['snippet'].encode('utf-8')+"")
From=message['payload']['headers'][0]['value']
fo.write(From+"");
da=message['payload']['headers'][1]['value']
fo.write(da+"\n");
for line in open("fooa.txt"):
print(line)
fo.close()
a=open("fooa.txt","r")
for wo in a:
match=re.findall(r':[\w]+',wo)
for word in match:
print(word.replace(':',' '))
db = MySQLdb.connect("localhost","testuser","mysql23","db1" )
cursor = db.cursor()
sql = """INSERT INTO customers((LeadName, CITY, SERVICE,CUSTOMER, MOBILE, EMAIL)
VALUES (, , , , )"""
try:
cursor.execute(sql)
db.commit()
except:
db.rollback()
db.close()
if __name__ == '__main__':
main()
Need help please!
You need to modify the message in a separate request, and remove the UNREAD-label.
POST https://www.googleapis.com/gmail/v1/users/me/messages/1533cb4d7dac1633/modify?access_token={ACCESS_TOKEN}
{
"removeLabelIds": [
"UNREAD"
]
}
If you're trying to mark the message as read, you will have to do something like:
gmail_service
.users()
.messages()
.modify(userId='me', id=message_id, body={'removeLabelIds': ['UNREAD']})
.execute()
What you can do with the Gmail API depends on what scope you've granted OAuth. Here's what you need to do:
Change SCOPES = 'https://www.googleapis.com/auth/gmail.readonly' to this:
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.modify'
]
Explanation: since marking an email as "unread" is a message modification, you need the 'gmail.modify' scope in order to use this API request. To see the full list of scopes, refer to Choose Auth Scopes.
Delete your token.pickle file and rerun the script. You'll need to do this in order to reauthorize the OAuth app with the new scopes, which will then generate a new token.pickle file.
Here's the code to mark an email as read in Python:
service.users().messages().modify(userId='me', id=message['id'], body={
'removeLabelIds': ['UNREAD']
}).execute()
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