Sending Emails with Python is too easy?
Published on Wednesday, Apr 24, 2024
Have you ever tried to make a Python project that can send you emails? Well, that's ez!
Sending Emails with Python
You tried several mailing service. SMTPLib? No, it did not work (to me too). MailGun? It is not always free.
Google Accounts used to have Less Secure Access, which was recently removed. However, in addition, they added a Gmail API which is more secure as well as with good functionallities.
I'll be demonstrating you step-by-step to how to use Python to send emails.
At the Conclusion section, you can see a project I made that also uses this Gmail API for verifying emails when you register on the website.
Setting up
Like always, a terminal and
virtualenv .venv
source .venv/source/activate
Boom!
Setting up the project
Go to GCP and create new project https://console.cloud.google.com/projectcreate
Once it's created, select it. From the sidebar, go to APIs & Services, Library and enable the Gmail API.
Then, you should see like this, asking you that you may need credentials. We do not need to create credentials from here. Just verify that you are at a similiar screen as me.
Go to OAuth Consent screen, and choose User Type as External.
You will have to specify things like:
App Name
User Support Email
App Logo
Developer's Email Address
Specify them as you wish. Application's home page, privacy policy, TOC etc is optional.
Any info you are specifying out of these are not shared. Even the app name does not make a difference, it is only what you will see when you are authenticating, not your users.
Add your email to user support and developer's email. You can specify app name like My Newsletter, it does not matter or change something worth.
Continue
Leave scopes as it is, and add your email (or the email you will use as your email sender, the from: email address, like maybe a test account's email address to it).
I recommend you to not use your main or valuable email address as a test user, or do not authenticate with it as Google auto-spam might report you.
OAuth created
Scroll down and verify you added your test account (the email address of the google account you own that you will be using as the email sender) is there, or add it.
You can publish your app however there is no need if you are doing this for your own. Additionally, they may ask you some questions so its fine in testing.
Go to credentials and click create credentials, choose OAuth Client ID and then...
The name is not shown to anyone except you so it's just fine as it is. Click CREATE.
Now as your credentials are created, download and save them to your project's directory as credentials.json
.
The coding
Create a file named app.py
in your project folder. Your project should be like this:
First, install the following libraries (make a requirements.txt and install from it, if you prefer):
google-api-python-client
google-auth-httplib2
google-auth-oauthlib
requests
The python script
This is your magical weapon to send emails! Put this code in your app.py
, confirming that you have a credentials.json
in the same directory and you installed all the packages.
import base64
import os.path
import pickle
from email.mime.text import MIMEText
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from requests import HTTPError
SCOPES = ["https://www.googleapis.com/auth/gmail.send"]
def email(to, subject, body):
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
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)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
message = MIMEText(body, 'html')
message['to'] = to
message['subject'] = subject
create_message = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}
try:
message = (service.users().messages().send(userId="me", body=create_message).execute())
return True
except HTTPError as error:
return False
I took this code lying on the surface of the web
Great. At the last, add few lines to test our application. Call the email
method with to
as your email (the destination) and some dummy subject and body (body allows HTML).
sendMyEmail = email(to="your_email_here@gmail.com", subject="Hi there bro!", body="What a <b>nice</b> day!")
if sendMyEmail:
print("Email sent successfully. Check your inbox!")
else:
print("Sorry, I cannot send the email.")
The email will not be sent on errors like Address Not Found or something, so try to set the
to
email to a account you own and then see.
Test the app
Finally, run the file.
It should open a browser window and give you a URL to authorize. This is only needed to be done once as your token will be saved to token.pickle
. Please addtoken.pickle
to your .gitignore
as it may leak access to your account.
Complete the authorization procedure with your testing account (the account will only work if it is in the Testing Users list for the OAuth app).
As you can see, you will be warned by Google as this app is on testing. We can continue as because we know what we are doing.
The app can send emails on behalf of my google account. So, use either your testing, or the product one, not your main!
Now the authorization flow has been completed, close the authorization tab and visit back to your terminal, did the email got sent?
It worked!
Ok good the email is sent. Can I check my inbox?
Seriously, I've got it in my inbox now. The email is in HTML, as the <b>
is working as intended to bold the text and...
There isn't visible differences to know if this email is automated or what, but it still shows in Primary (Person-to-person emails go in primary).
Wrapping up
Congrats on making a python project that can send emails! Here's what you can use this for:
Adding email vertification for signup/login
Making your newsletter website (flask is very easy with this)
Just for a example, visit <cutyoururl.tech>, my URL shortener with Python+Flask+Gmail API that uses this same method to verify emails. GitHub: {% embed https://github.com/ashishagarwal2023/CutYourURL %}. Can you give it a star?