gmail_api_in_python

Gmail is the most popular mail service as of today, it’s used by individuals and organizations. Many of its features are enhanced with AI, including its security (and detection of fraud emails) and its suggestions when writing emails.

The Gmail API is a RESTful API that can be used to access Gmail mailboxes and send email. For most web applications the Gmail API is the best choice for authorized access to a user’s Gmail data and is suitable for various applications, such as: Read-only mail extraction, indexing, and backup and for email marketing or automatic email management. Here, we have an example demonstrating how to use Gmail API in Python.

Software Requirements

  • Python (2.6 or higher)
  • Windows 10
  • A Google Account with Gmail Enabled
  • Beautiful Soup library
  • Google API client and Google OAuth libraries

Installation for Python

  • pip install google-auth-httplib2
  • pip install google-auth-oauthlib
  • pip install google-api-python-client
  • pip install beautifulsoup4

Enabling Gmail API

In this article, we will see how to enable Gmail API for your Gmail account. You must set up your Google Cloud console to interact with the Gmail API, so follow these steps:

Step-1: Sign in https://console.cloud.google.com/getting-started

Step-2:  create a New Project or continue with an existing project.

Step-3: Enabling Gmail API

Example:

Project-> useapi-test-12345

APP Name-> test-kkpk-api

You should enable Gmail API as per below dashboard screenshot, we first enable the Google mail API, and use the search bar to search for Gmail API, click on it, and then enable.

Sending Emails Using Gmail API in Python

If you already used a Google API before, it is basically reading the credentials.json and saving it to token.pickle file after authenticating with Google in your browser, we save the token so the second time we run the code we shouldn’t authenticate again.

Step-1: All above steps of “Enabling Gmail API” section should be done.

Step-2: Download the credentials file in JSON format which you must use in the code. Once you download the JSON file, rename the file with name: credentials so your file name should be credentials.json for better reading

Step-3: OAuth Consent Screen: Add the user as developer to access your Gmail account, you can use your email id also.

Step-4: Once you will execute the gmail_authenticate function of below code you will get one token (token.pickle) file with Gmail google authenticate permission where you must do some actions for login with email id and PWD on web browser which is opened by code during the execution.

Token file would be created with same root directory where you have python code file, if you want to create with any specific path, you must update the proper path.

If you cleared the cache / cookies of web browser and now you want to connect with gmail_authenticate function, you will get the below error:

RefreshError: (‘invalid_grant: Bad Request’, {‘error’: ‘invalid_grant’, ‘error_description’: ‘Bad Request’})

To remove the above error, you must follow the below steps:

  1. Delete the old token.pickle file.
  2. Execute the code function  gmail_authenticate and repeat same action again which you have done first time in Step-4, you will see new token.pickle file and now you can start send emails via below python code.G

Python Code For Send Email

import os
import pickle

# Gmail API utils
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# for encoding/decoding messages in base64
from base64 import urlsafe_b64decode, urlsafe_b64encode

# for dealing with attachement MIME types
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from mimetypes import guess_type as guess_mime_type

# Request all access (permission to read/send/receive emails, manage the inbox, and more)
SCOPES = ['https://mail.google.com/']
our_email = 'xyz@gmail.com'

def gmail_authenticate():
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 availablle, 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)
return build('gmail', 'v1', credentials=creds)

# get the Gmail API service
service = gmail_authenticate()

# Adds the attachment with the given filename to the given message
def add_attachment(message, filename):
content_type, encoding = guess_mime_type(filename)
if content_type is None or encoding is not None:
content_type = 'application/octet-stream'
main_type, sub_type = content_type.split('/', 1)
if main_type == 'text':
fp = open(filename, 'rb')
msg = MIMEText(fp.read().decode(), _subtype=sub_type)
fp.close()
elif main_type == 'image':
fp = open(filename, 'rb')
msg = MIMEImage(fp.read(), _subtype=sub_type)
fp.close()
elif main_type == 'audio':
fp = open(filename, 'rb')
msg = MIMEAudio(fp.read(), _subtype=sub_type)
fp.close()
else:
fp = open(filename, 'rb')
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fp.read())
fp.close()
filename = os.path.basename(filename)
msg.add_header('Content-Disposition', 'attachment', filename=filename)
message.attach(msg)

def build_message(destination, obj, body, attachments=[]):
if not attachments: # no attachments given
message = MIMEText(body)
message['to'] = destination
message['from'] = our_email
message['subject'] = obj
else:
message = MIMEMultipart()
message['to'] = destination
message['from'] = our_email
message['subject'] = obj
message.attach(MIMEText(body))
for filename in attachments:
add_attachment(message, filename)
return {'raw': urlsafe_b64encode(message.as_bytes()).decode()}

def send_message(service, destination, obj, body, attachments=[]):
return service.users().messages().send(
userId="me",
body=build_message(destination, obj, body, attachments)
).execute()

# test send email
To="abc@gmail.com"
Subject="This is a subject"
Body="This is the body of the email"
attached1="gmail_api.txt"
attached2="gmail_api.jpg"send_message(service, To, Subject, Body, [attached1, attached2])