Search code examples
pythongoogle-apipython-requestsgoogle-oauthgmail-api

Gmail API: How to simply authenticate a User and get a list of their messages?


I'm trying to build a simple python script to access gmail's API and organize certain email messages inmy inbox into a csv file.

I see in the below documentation that accessing the messages is done using the user's (mine in this case) email address.

messages.list

I'm running into difficulty accessing the API. I'm getting the below error:

"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."

I was hoping to build a light weight script not a web application. Does anyone know if there is a way I can authenticate my own email address in a script?

PS: I suppose I could use selenium to automatically sign in but I was wondering if there was a way to do this using gmail's API.


Solution

  • You need to understand that the data you are trying to access is private user data. This is data owned by a user that being you, which means your application need to be "authorized" by the user "you" to access their data.

    We do this with a method called Oauth2, it will allow your application to request consent for access to read the users emails in this case.

    In order to use Oauth2 you must first register your applcation on Google Developer console and set up a few things, this will identify your application to Google.

    All of this is explained in the Python quick-start for gmail. Once you have that working you should be able to change the code to use message.list instead of labels.list.

    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
    
    # If modifying these scopes, delete the file token.pickle.
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
    
    def main():
        """Shows basic usage of the Gmail API.
        Lists the user's Gmail labels.
        """
        creds = None
        # The file token.pickle stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists('token.pickle'):
            with open('token.pickle', 'rb') as token:
                creds = pickle.load(token)
        # If there are no (valid) credentials available, let the user log in.
        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(
                    'credentials.json', SCOPES)
                creds = flow.run_local_server(port=0)
            # Save the credentials for the next run
            with open('token.pickle', 'wb') as token:
                pickle.dump(creds, token)
    
        service = build('gmail', 'v1', credentials=creds)
    
        # Call the Gmail API
        results = service.users().labels().list(userId='me').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()