Gmail API Email Sender
This guide demonstrates how to send emails programmatically using the Gmail API. This approach uses OAuth 2.0 for authentication, which is more secure and reliable than using smtplib with "Less Secure Apps" enabled (which Google has largely deprecated).
Modules Used:
google-api-python-client: To interact with Google APIs.google-auth-oauthlib: For handling the OAuth 2.0 authentication flow.email: To construct the email message content.base64: To encode the message for the API.
Prerequisites
- Google Cloud Console: Go to the Google Cloud Console.
- Create Project: Create a new project.
- Enable API: Search for "Gmail API" and enable it.
- Credentials:
- Go to "Credentials" -> "Create Credentials" -> "OAuth client ID".
- Configure the Consent Screen (External, Test User = your email).
- Application type: Desktop App.
- Download the JSON file and rename it to
credentials.json. - Place
credentials.jsonin the same directory as your script.
Installation
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
The Code
Save this as gmail_sender.py.
import os.path
import base64
import argparse
from email.message import EmailMessage
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
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.send']
def authenticate():
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:
if not os.path.exists('credentials.json'):
print("Error: credentials.json not found.")
return None
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())
return creds
def send_email(to_email, subject, body):
creds = authenticate()
if not creds:
return
try:
service = build('gmail', 'v1', credentials=creds)
message = EmailMessage()
message.set_content(body)
message['To'] = to_email
message['From'] = 'me' # 'me' is a special value indicating the authenticated user
message['Subject'] = subject
# Encode the message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {'raw': encoded_message}
# Send
send_message = (service.users().messages().send(userId="me", body=create_message).execute())
print(f'Message Id: {send_message["id"]}')
print(f"Email sent successfully to {to_email}")
except HttpError as error:
print(f'An error occurred: {error}')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Gmail API Email Sender")
parser.add_argument("to", help="Recipient email address")
parser.add_argument("subject", help="Email subject")
parser.add_argument("body", help="Email body text")
args = parser.parse_args()
send_email(args.to, args.subject, args.body)
Usage
-
First Run:
python gmail_sender.py recipient@example.com "Hello" "This is a test email from Python."A browser window will open asking you to log in and authorize the app.
-
Subsequent Runs: The script will use the saved
token.jsonto send emails instantly without user interaction.