Last modified: Feb 01, 2026 By Alexander Williams

Gmail API Python Guide for Automation

Do you manage many emails? Do you need to send automated reports? The Gmail API with Python is your solution. It lets you control Gmail from your code.

This guide is for beginners. We will start from zero. You will learn to set up the API, authenticate, and write useful scripts. By the end, you can automate your email tasks.

What is the Gmail API?

The Gmail API is a RESTful interface. It provides programmatic access to Gmail mailboxes. You can read, send, search, and manage emails.

It is more powerful than simple SMTP. You can manage labels, drafts, and threads. It is perfect for building email automation tools.

If you are new to APIs, our Python API Calls Guide for Beginners is a great starting point.

Prerequisites and Setup

You need a few things before starting. First, ensure you have Python installed. You also need a Google Cloud project with the API enabled.

Let's go through the setup step-by-step.

Step 1: Enable the Gmail API

Go to the Google Cloud Console. Create a new project or select an existing one. Navigate to "APIs & Services" > "Library".

Search for "Gmail API". Click on it and press the "Enable" button. This allows your project to use the Gmail service.

Step 2: Create Credentials

After enabling the API, go to "Credentials". Click "Create Credentials" and choose "OAuth 2.0 Client ID".

Select "Desktop app" as the application type. Name it something like "Gmail Python Client". Click "Create".

Download the JSON credentials file. Rename it to credentials.json and place it in your project folder. Keep this file secret.

Step 3: Install Required Libraries

Open your terminal or command prompt. Install the Google Client Library and related tools using pip.


pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    

Authenticating with OAuth 2.0

Authentication is the first step in your script. The Gmail API uses OAuth 2.0. This ensures secure access to user data.

We will write a helper function to handle this. It will create a service object we can use to make API calls.


import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

# Define the permissions your app needs
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']

def authenticate_gmail():
    """Handles OAuth 2.0 authentication and returns a service object."""
    creds = None
    # The file token.json stores the user's access and refresh tokens
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # 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.json', 'w') as token:
            token.write(creds.to_json())
    # Build the Gmail API service
    service = build('gmail', 'v1', credentials=creds)
    return service

# Get the authenticated service
gmail_service = authenticate_gmail()
print("Authentication successful. Service object created.")
    

The first run opens a browser for login. It then saves a token.json file. Future runs use this token.

The build function creates our main service object. We use gmail_service for all API calls.

Reading Emails from Your Inbox

Let's fetch a list of recent emails. We will use the users.messages.list method. Then we get details for each message.


def list_messages(service, user_id='me', max_results=5):
    """Lists the most recent emails in the user's inbox."""
    try:
        # Call the Gmail API
        results = service.users().messages().list(
            userId=user_id, maxResults=max_results, labelIds=['INBOX']).execute()
        messages = results.get('messages', [])

        if not messages:
            print('No messages found.')
            return []

        print(f'Found {len(messages)} messages:')
        message_details = []
        for msg in messages:
            # Get full message details
            msg_detail = service.users().messages().get(
                userId=user_id, id=msg['id']).execute()
            # Extract headers
            headers = msg_detail['payload']['headers']
            subject = next((h['value'] for h in headers if h['name'] == 'Subject'), 'No Subject')
            sender = next((h['value'] for h in headers if h['name'] == 'From'), 'Unknown Sender')
            print(f"ID: {msg['id']} | From: {sender} | Subject: {subject}")
            message_details.append(msg_detail)
        return message_details
    except Exception as error:
        print(f'An error occurred: {error}')
        return []

# Use our service to list messages
messages = list_messages(gmail_service)
    

Found 5 messages:
ID: 189abc... | From: [email protected] | Subject: Weekly Digest
ID: 188xyz... | From: [email protected] | Subject: Your Statement
ID: 187def... | From: [email protected] | Subject: Meeting Notes
...
    

This script lists your latest inbox emails. It shows the sender and subject. You can modify it to search or filter emails.

Sending an Email with Python

To send emails, you need a different scope. Update the SCOPES to include send permission. Then create and send a message.


import base64
from email.mime.text import MIMEText

# Update SCOPES for sending (re-run authentication)
SCOPES = ['https://www.googleapis.com/auth/gmail.send']

def create_message(sender, to, subject, body_text):
    """Creates a MIME message for an email."""
    message = MIMEText(body_text)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject
    # Encode the message in base64 URL-safe format
    raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
    return {'raw': raw_message}

def send_message(service, user_id, message):
    """Sends an email message."""
    try:
        sent_message = service.users().messages().send(
            userId=user_id, body=message).execute()
        print(f'Message Id: {sent_message["id"]} sent successfully.')
        return sent_message
    except Exception as error:
        print(f'An error occurred: {error}')
        return None

# Re-authenticate with the new send scope
gmail_service_send = authenticate_gmail() #