Gmail API in Python

The Gmail API in Python allows the developer to programmatically interact with Gmail accounts to send, read, and manage emails. It provides a more granular control than the standard IMAP/SMTP email protocols, and it supports features like drafts, attachments, and email threading. Below is a detailed explanation:

1. Prerequisites

Before starting, ensure you have:

  • A Google account.
  • Python installed on your system.
  • The google-auth, google-auth-oauthlib, and google-api-python-client libraries installed. Install them with:
pip install google-auth google-auth-oauthlib google-api-python-client

2. Turn ON the Gmail API

  1. Get to Google Cloud Console.
  2. Create new project or select already existing project.
  3. Turn On the Gmail API for that project;
    • Go to APIs & Services > Library.
    • Search the term “Gmail API” then click on ENABLE.
  4. Set up OAuth consent screen for APIs & Services > OAuth consent screen:
    • Select as “External.”
    • Fill the required fields there and then save.
  5. Create credentials:
    • Go to APIs & Services > Credentials.
    • Click “Create Credentials” > “OAuth 2.0 Client IDs”.
    • Choose “Desktop App” as the application type.
    • Download the JSON file (commonly named credentials.json).

3. Authentication Setup

Use the credentials.json file to authenticate the app and generate a token. This is how your app accesses Gmail.

Code for Authentication:

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
import os

# Define the scope (read, send, and manage emails)
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly',  # For reading emails
          'https://www.googleapis.com/auth/gmail.send',     # For sending emails
          'https://www.googleapis.com/auth/gmail.modify']   # For modifying emails

def authenticate_gmail():
    creds = None
    # Token file to store credentials
    token_file = 'token.json'

    if os.path.exists(token_file):
        from google.oauth2.credentials import Credentials
        creds = Credentials.from_authorized_user_file(token_file, SCOPES)

    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            from google.auth.transport.requests import Request
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)

        # Save credentials for the next run
        with open(token_file, 'w') as token:
            token.write(creds.to_json())

    return creds

# Authenticate and build the Gmail service
creds = authenticate_gmail()
service = build('gmail', 'v1', credentials=creds)
print("Gmail API service initialized.")

4. Common Operations

4.1. List Messages

Retrieve a list of emails in your Gmail inbox.

def list_messages(service, user_id='me', query=''):
    results = service.users().messages().list(userId=user_id, q=query).execute()
    messages = results.get('messages', [])
    
    if not messages:
        print('No messages found.')
    else:
        print('Messages:')
        for message in messages[:5]:  # Fetch the first 5 messages
            print(f"Message ID: {message['id']}")

4.2. Get Message Details

Fetch the content of an email.

def get_message(service, user_id='me', msg_id='MESSAGE_ID'):
    message = service.users().messages().get(userId=user_id, id=msg_id).execute()
    print('Message snippet:', message['snippet'])

4.3. Send an Email

To send an email, you need to encode the message in base64 format.

import base64
from email.mime.text import MIMEText

def create_message(sender, to, subject, message_text):
    message = MIMEText(message_text)
    message['to'] = to
    message['from'] = sender
    message['subject'] = subject
    raw = base64.urlsafe_b64encode(message.as_bytes()).decode()
    return {'raw': raw}

def send_message(service, user_id='me', message):
    try:
        sent_message = service.users().messages().send(userId=user_id, body=message).execute()
        print('Message Id:', sent_message['id'])
    except Exception as error:
        print('An error occurred:', error)

# Example usage
message = create_message("your_email@gmail.com", "recipient_email@gmail.com", "Test Subject", "Hello, this is a test email!")
send_message(service, "me", message)

4.4. Modify Emails (Mark as Read/Unread)

def modify_message(service, user_id='me', msg_id='MESSAGE_ID', labels_to_add=None, labels_to_remove=None):
    labels = {
        'addLabelIds': labels_to_add or [],
        'removeLabelIds': labels_to_remove or []
    }
    message = service.users().messages().modify(userId=user_id, id=msg_id, body=labels).execute()
    print(f'Modified message: {msg_id}')

5. Error Handling

The Gmail API may return errors (e.g., quota exceeded, unauthorized). Handle them using try-except blocks.

Example:

try:
    # Your Gmail API call here
    pass
except Exception as error:
    print(f'An error occurred: {error}')

6. Resources

By following these steps, you can efficiently interact with Gmail using Python.