Send Gmails with Python: Gmail API & OAuth 2.0

Learn to send emails programmatically using Python and the Gmail API with secure OAuth 2.0 authentication. A comprehensive guide for developers.

Sending Emails with Python Using the Gmail API

This guide provides a comprehensive walkthrough on how to programmatically send emails using your Gmail account with Python. The Gmail API, coupled with OAuth 2.0 authentication, offers a powerful and secure method for interacting with your Gmail mailbox. You'll learn to set up the API, authenticate your Python application, and send emails efficiently.

What is the Gmail API?

The Gmail API is a RESTful interface that allows developers to interact with Gmail programmatically. It grants access to Gmail mailboxes, enabling operations such as sending, searching, reading, and deleting emails.

Step-by-Step Guide to Sending Emails with Python and the Gmail API

Follow these steps to integrate the Gmail API into your Python projects for sending emails.

Step 1: Enable the Gmail API and Obtain OAuth Credentials

  1. Navigate to Google Cloud Console: Go to https://console.cloud.google.com/.
  2. Create or Select a Project: Either create a new Google Cloud project or select an existing one.
  3. Enable the Gmail API:
    • Go to APIs & Services > Library.
    • Search for "Gmail API" and click Enable.
  4. Create OAuth Client ID:
    • Go to APIs & Services > Credentials.
    • Click Create Credentials > OAuth client ID.
    • Select Desktop app as the application type.
    • Click Create.
  5. Download Credentials: After creation, you will be prompted to download the credentials.json file.
    • Crucially: Save this credentials.json file in the same directory as your Python script. This file is essential for authenticating your application.

Step 2: Install Required Python Libraries

You'll need to install the necessary Google client libraries for Python. Use pip to install them:

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

Step 3: Python Script to Authenticate and Send Email

Create a Python file (e.g., send_gmail.py) and add the following code. This script handles authentication and the email sending process.

import os.path
import base64
from email.message import EmailMessage

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

# Define the scope for sending emails
SCOPES = ['https://www.googleapis.com/auth/gmail.send']

def authenticate_gmail():
    """Authenticates with the Gmail API and returns the service object."""
    creds = None
    # The file token.json 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.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())

    service = build('gmail', 'v1', credentials=creds)
    return service

def create_message(sender, to, subject, message_text):
    """Creates an email message in RFC 2822 format."""
    message = EmailMessage()
    message.set_content(message_text)
    message['To'] = to
    message['From'] = sender
    message['Subject'] = subject

    # Encode the message as base64 for sending
    encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
    return {'raw': encoded_message}

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

if __name__ == '__main__':
    # Authenticate to Gmail
    gmail_service = authenticate_gmail()

    # Define email details
    sender_email = "your_email@gmail.com"  # Replace with your Gmail address
    recipient_email = "recipient@example.com" # Replace with the recipient's email address
    email_subject = "Test Email from Python Gmail API"
    email_body = "This is a test email sent using the Gmail API and Python."

    # Create the email message
    email_message = create_message(sender_email, recipient_email, email_subject, email_body)

    # Send the email
    send_email(gmail_service, "me", email_message)

Important Notes:

  • Replace Placeholders: Remember to replace "your_email@gmail.com" with your actual Gmail address and "recipient@example.com" with the intended recipient's email address.
  • token.json: The token.json file stores your authorization tokens. It's generated after the initial successful authentication and allows subsequent runs of the script to proceed without re-authentication. Keep it secure.
  • "me" User ID: The string "me" in send_email(gmail_service, "me", email_message) refers to the currently authenticated user (your Gmail account).

Benefits of Using the Gmail API Over SMTP

The Gmail API offers significant advantages over traditional SMTP for sending emails:

  • Enhanced Security: Utilizes OAuth 2.0 for secure, token-based authentication, eliminating the need to expose your Gmail password directly in your scripts.
  • Greater Functionality: Provides comprehensive control over your Gmail account, allowing you to manage drafts, labels, attachments, read emails, and more, beyond just sending.
  • Scalability and Integration: Ideal for building robust email automation tools, notification systems, customer support platforms, and data analysis applications.

Final Thoughts

Integrating the Gmail API with Python empowers you to build sophisticated email functionalities securely and efficiently. By following these steps, you can easily authenticate your applications and send emails programmatically, opening up possibilities for automated workflows, notifications, and enhanced user communication.


  • What is the Gmail API and how does it differ from using SMTP directly for sending emails? The Gmail API is a programmatic interface for interacting with Gmail, offering advanced features and OAuth 2.0 security. SMTP is a protocol for sending emails, which, when used with Gmail directly, often requires less secure methods like app passwords or OAuth credentials configured differently. The API provides more control over the entire Gmail experience.
  • How do you authenticate a Python application to use the Gmail API? Authentication is primarily done using OAuth 2.0. This involves obtaining credentials.json from the Google Cloud Console and using libraries like google-auth-oauthlib to guide the user through an authorization flow, resulting in a token.json file for future access.
  • Explain the role of OAuth 2.0 in Gmail API authentication. OAuth 2.0 is an authorization framework that allows your Python application to access a user's Gmail data without needing their password. It uses access tokens that are granted for specific scopes (permissions) and have an expiration time.
  • What Python libraries are required to interact with the Gmail API? The essential libraries are google-api-python-client for building the service object, google-auth-httplib2 for HTTP transport, and google-auth-oauthlib for the OAuth 2.0 authorization flow.
  • How do you create and send an email message using the Gmail API in Python? You create an EmailMessage object, set the sender, recipient, subject, and body. This message is then encoded into a raw, base64 string. This raw string is sent to the users().messages().send() endpoint of the Gmail API.
  • What is the purpose of the token.json file in Gmail API integration? The token.json file stores the OAuth 2.0 access and refresh tokens after the initial user authorization. This allows the application to obtain new access tokens without requiring the user to re-authenticate every time the script is run.
  • Can the Gmail API send emails with attachments? If yes, how? Yes, the Gmail API can send emails with attachments. You would typically create a multipart email message (e.g., using Python's email.mime module), add the attachment as a MIME part, encode the entire message into raw base64, and then send it via the API.
  • How does the Gmail API improve security compared to traditional SMTP email sending? The Gmail API enforces OAuth 2.0, which means your application never handles or stores the user's actual Gmail password. This significantly reduces the risk of password compromise. SMTP, especially basic authentication, can be less secure if not implemented with TLS/SSL.
  • What are the Gmail API scopes and why are they important? Scopes define the specific permissions your application requests for accessing a user's Gmail data (e.g., gmail.send, gmail.readonly, gmail.modify). They are crucial for adhering to the principle of least privilege, ensuring your application only has access to the data it needs, thereby enhancing security and user privacy.
  • How would you handle token expiration and refresh in a Gmail API Python app? The google-auth-oauthlib library, specifically the Credentials object, handles token expiration and refresh automatically when you use the creds.refresh(Request()) method. The refresh token stored in token.json is used to obtain a new, valid access token when the current one expires.