Search code examples
python-3.xgmailgmail-apigoogle-api-python-clientservice-accounts

error code 400 when trying to read GMAIL using a service account


I'm using Gmail's API to read messages to an inbox. I have a project in the cloud developer portfolio. I sign in with the account whose inbox I have to get data from. I've made a service account without any roles etc and downloaded the required key. I've built a resource using:

scopes = ["https://www.googleapis.com/auth/gmail.readonly"]
credentials = service_account.Credentials.from_service_account_files(path, scopes=scopes)
service = build(
   "gmail",
   "v1",
   credentials=credentials
)

Which is fine. but when I try and pull information from the inbox:

responses = service.users().messages().list(userId="me").execute()

which gives me:

googleapiclient.errors.HttpError: <HttpError 400 when requesting <email> returned "Precondition check failed.">

I've tried changing "me" to the email, setting some roles. I can access this by using OAuth credentials but not with the service key. What could be causing my issue?


Solution

  • I will just try to expand on what @DalmTo said in the comments.

    Service Accounts

    Service accounts are special accounts that work without human interaction, they can use some google's API as you would in your normal account. There are some API (like Gmail) that cannot be accessible as a Service account because that would cause problems, like spam or problems.

    But in a nutshell service accounts are fully independent accounts that can use the API without human interaction.


    Domain Wide Delegation

    There are some times that in a company (domain) with enterprise behavior there are some task that should be done to all the users, backup all drive files, check emails for spam malicious content or whatever you can imagine. For that the service account can have a special behavior to substitute an user. So the service account is delegated with the user access to the API inside the domain.


    Answering your question

    For your specific case:

    • You cannot use GMail API with a Service account
    • You cannot use Domain Wide Delegation if you don't have a domain to start with

    Alternatives

    So at this point your set up makes impossible the use of services accounts, so the only way is using your regular account with regular OAuth authentication.

    I won't go into detail because this is not what you have asked for, but in case you are not familiar with it, there are ways to use the refresh token so you only have to authorize your app the first time and whenever the refresh token becomes invalid.