Python Email-Bot with GCP and Gmail API

Intro

Need to create an email dispatch server? Gotta spam your friends with fantasy league updates?

Checklist

Before you get started, make sure you have the following:

  • A GCP Account

Part 1: Google Cloud Configurations

  1. Create a new google cloud project
Creating your new project in GCP
Make sure to click enable!
Download the generated key!

Part 2: Python Script

Note: Most of these steps can be recreated using the Quickstart guide in the Gmail API documentation here

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
from __future__ import print_function

import base64
import mimetypes
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

SCOPES = ['https://www.googleapis.com/auth/gmail.compose']
creds = None

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())
  • If there’s no valid token, use the downloaded credentials and create a new token.
try:
# create gmail api client
service = build('gmail', 'v1', credentials=creds)
mime_message = EmailMessage()

# headers
mime_message['To'] = "YOUR_EMAIL"
mime_message['From'] = 'TARGET_EMAIL'
mime_message['Subject'] = 'Sent from automated email server'

# text
mime_message.set_content(
"<p> Hi, this is automated mail with attachment on behalf of a Gmail bot</p><p>No need to reply, dw</p> "
, subtype="html"
)

# attachment
attachment_filename = 'YOURFILE.pdf'
# guessing the MIME type
type_subtype, _ = mimetypes.guess_type(attachment_filename)
maintype, subtype = type_subtype.split('/')

with open(attachment_filename, 'rb') as fp:
attachment_data = fp.read()
mime_message.add_attachment(attachment_data, maintype, subtype, filename="YOUR_FILENAME.pdf")

encoded_message = base64.urlsafe_b64encode(mime_message.as_bytes()).decode()

create_message = {
'raw': encoded_message
}
# pylint: disable=E1101
send_message = (service.users().messages().send
(userId="me", body=create_message).execute())
except HttpError as error:
print(F'An error occurred: {error}')
send_message = None
return send_message
from __future__ import print_function

import base64
import mimetypes
import os
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

SCOPES = ['https://www.googleapis.com/auth/gmail.compose']

def gmail_send_attachment():

creds = None

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())

try:
# create gmail api client
service = build('gmail', 'v1', credentials=creds)
mime_message = EmailMessage()

# headers
mime_message['To'] = "YOUR_EMAIL"
mime_message['From'] = 'TARGET_EMAIL'
mime_message['Subject'] = 'Sent from automated email server'

# text
mime_message.set_content(
"<p> Hi, this is automated mail with attachment on behalf of a Gmail bot</p><p>No need to reply, dw</p> "
, subtype="html"
)

# attachment
attachment_filename = 'YOURFILE.pdf'
# guessing the MIME type
type_subtype, _ = mimetypes.guess_type(attachment_filename)
maintype, subtype = type_subtype.split('/')

with open(attachment_filename, 'rb') as fp:
attachment_data = fp.read()
mime_message.add_attachment(attachment_data, maintype, subtype, filename="YOUR_FILENAME.pdf")

encoded_message = base64.urlsafe_b64encode(mime_message.as_bytes()).decode()

create_message = {
'raw': encoded_message
}
# pylint: disable=E1101
send_message = (service.users().messages().send
(userId="me", body=create_message).execute())
except HttpError as error:
print(F'An error occurred: {error}')
send_message = None
return send_message

if __name__ == '__main__':
gmail_send_attachment()

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store