lollercoaster lollercoaster - 3 years ago 260
JSON Question

gmail python api authentication

I created a project in the Google Developer dashboard, gave it access to the Gmail API, and downloaded my credentials as a JSON file.

Then I changed the JSON credential file path here and tried to run the quickstart example, it failed with:

In [2]: run quickstart.py
---------------------------------------------------------------------------
InvalidClientSecretsError Traceback (most recent call last)
/Users/me/Code/gmail/quickstart.py in <module>()
19
20 # Start the OAuth flow to retrieve credentials
---> 21 flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
22 http = httplib2.Http()
23

/Users/me/.virtualenvs/nlp/lib/python2.7/site-packages/oauth2client/util.pyc in positional_wrapper(*args, **kwargs)
130 else: # IGNORE
131 pass
--> 132 return wrapped(*args, **kwargs)
133 return positional_wrapper
134

/Users/me/.virtualenvs/nlp/lib/python2.7/site-packages/oauth2client/client.pyc in flow_from_clientsecrets(filename, scope, redirect_uri, message, cache, login_hint, device_uri)
1987 """
1988 try:
-> 1989 client_type, client_info = clientsecrets.loadfile(filename, cache=cache)
1990 if client_type in (clientsecrets.TYPE_WEB, clientsecrets.TYPE_INSTALLED):
1991 constructor_kwargs = {

/Users/me/.virtualenvs/nlp/lib/python2.7/site-packages/oauth2client/clientsecrets.pyc in loadfile(filename, cache)
141
142 if not cache:
--> 143 return _loadfile(filename)
144
145 obj = cache.get(filename, namespace=_SECRET_NAMESPACE)

/Users/me/.virtualenvs/nlp/lib/python2.7/site-packages/oauth2client/clientsecrets.pyc in _loadfile(filename)
104 except IOError:
105 raise InvalidClientSecretsError('File not found: "%s"' % filename)
--> 106 return _validate_clientsecrets(obj)
107
108

/Users/me/.virtualenvs/nlp/lib/python2.7/site-packages/oauth2client/clientsecrets.pyc in _validate_clientsecrets(obj)
71 def _validate_clientsecrets(obj):
72 if obj is None or len(obj) != 1:
---> 73 raise InvalidClientSecretsError('Invalid file format.')
74 client_type = tuple(obj)[0]
75 if client_type not in VALID_CLIENT:

InvalidClientSecretsError: Invalid file format.


Here's the code:

#!/usr/bin/python

import httplib2

from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run


# Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'gmail-api-eeac5a33ec79.json'

# Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly'

# Location of the credentials storage file
STORAGE = Storage('gmail.storage')

# Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http()

# Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
credentials = run(flow, STORAGE, http=http)

# Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http)

# Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http)

# Retrieve a page of threads
threads = gmail_service.users().threads().list(userId='me').execute()

# Print ID for each thread
if threads['threads']:
for thread in threads['threads']:
print 'Thread ID: %s' % (thread['id'])


I didn't change the JSON file -- just downloaded it from the Developer's console. I'm really offput that Gmail's API is so difficult to get going -- anyone know what I'm doing wrong?

Raf Raf
Answer Source

When creating new Client ID make sure you select either Web application or Installed application.

If you selected Service account then the JSON received has a different format and another process has to be followed:

Service accounts

Google APIs such as the Prediction API and Google Cloud Storage can act on behalf of your application without accessing user information. In these situations your application needs to prove its own identity to the API, but no user consent is necessary. Similarly, in enterprise scenarios, your application can request delegated access to some resources.

For these types of server-to-server interactions you need a service account, which is an account that belongs to your application instead of to an individual end-user. Your application calls Google APIs on behalf of the service account, and user consent is not required. (In non-service-account scenarios, your application calls Google APIs on behalf of end-users, and user consent is sometimes required.)

Note: These service-account scenarios require applications to create and cryptographically sign JSON Web Tokens (JWTs). We strongly encourage you to use a library to perform these tasks. If you write this code without using a library that abstracts token creation and signing, you might make errors that would have a severe impact on the security of your application. For a list of libraries that support this scenario, see the service-account documentation. A service account's credentials, which you obtain from the Google Developers Console, include a generated email address that is unique, a client ID, and at least one public/private key pair. You use the client ID and one private key to create a signed JWT and construct an access-token request in the appropriate format. Your application then sends the token request to the Google OAuth 2.0 Authorization Server, which returns an access token. The application uses the token to access a Google API. When the token expires, the application repeats the process.

from google's dev pages.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download