Nerd For Tech
Published in

Nerd For Tech

How to Send Email Using Python FastAPI

Photo by Tianyi Ma on Unsplash

Let’s start with an introduction about FastAPI before we jump into the main topic. What is FastAPI?

Directly taken from the official documentation:

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.

FastAPI has gained a lot of popularity these days because of its speed and easy to set up. It’s probably still debatable to decide which one is better between FastAPI, Flask (in addition to new Flask 2.0), and Django. But in my opinion, it goes back to our use cases. You can read the detail here https://www.section.io/engineering-education/choosing-between-django-flask-and-fastapi/.

Jump to the main topic, let’s create a simple app to send email using FastAPI in two ways, with and without background task.

Before that

In this article, we will use Gmail account to send email and to make sure everything is working properly, you’ll need a Gmail account to do so. Make sure you set Allow less secure apps to On, in your google account settings. This is how you can do that:

  1. Click manage your Google account on your account icon (on top right corner).

2. Go to the security tab.

3. You’ll find a section on this page, to allow less secure apps. (here, I have set it on)

4. Turn this setting on.

This won’t work if your account has two-factor authentication enabled. The choices are you can create a separate account or create application-specific passwords.

If you still get authentication errors, you can try this:

  1. Display unlock captcha. (https://accounts.google.com/DisplayUnlockCaptcha)
  2. Enable IMAP access. (https://mail.google.com/mail/#settings/fwdandpop)

Create The App

Configure virtual environment

To isolate the environment for this app, we have to use a virtual environment, in this case, I will use pipenv to manage virtual environment.

pipenv shell

This command will spawn a shell within a virtual environment and generate Pipfile. Then, we can install the dependencies we need.

pipenv install fastapi fastapi-mail uvicorn python-dotenv

Create a main.py file and put some template code in there.

import uvicorn
from fastapi import FastAPI, BackgroundTasks
from send_email import send_email_background, send_email_async
app = FastAPI(title='How to Send Email')@app.get('/')
def index():
return 'Hello World'
if __name__ == '__main__':
uvicorn.run('main:app', reload=True)

To run the app, you can type the command python main.py . This command will launch the server, then you can look at the documentation generated by FastAPI by going to http://localhost:8000/docs.

Nice…

Now, create .env file to store sensitive data.

MAIL_USERNAME=<GMAIL_USERNAME>
MAIL_PASSWORD=<GMAIL_PASSWORD>
MAIL_FROM=<SENDER_ADDRESS>
MAIL_PORT=587
MAIL_SERVER=smtp.gmail.com
MAIL_FROM_NAME=<TITLE_FOR_MAIL>

Create a file named send_email.py , then load the .env .

import os
from fastapi import BackgroundTasks
from fastapi_mail import FastMail, MessageSchema, ConnectionConfig
from dotenv import load_dotenv
load_dotenv('.env')
class Envs:
MAIL_USERNAME = os.getenv('MAIL_USERNAME')
MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')
MAIL_FROM = os.getenv('MAIL_FROM')
MAIL_PORT = int(os.getenv('MAIL_PORT'))
MAIL_SERVER = os.getenv('MAIL_SERVER')
MAIL_FROM_NAME = os.getenv('MAIN_FROM_NAME')

We have the imports we need and settings (we need this for the FastAPI MAIL connection config). Then write the connection config and the code to send the email.

conf = ConnectionConfig(
MAIL_USERNAME=Envs.MAIL_USERNAME,
MAIL_PASSWORD=Envs.MAIL_PASSWORD,
MAIL_FROM=Envs.MAIL_FROM,
MAIL_PORT=Envs.MAIL_PORT,
MAIL_SERVER=Envs.MAIL_SERVER,
MAIL_FROM_NAME=Envs.MAIL_FROM_NAME,
MAIL_TLS=True,
MAIL_SSL=False,
USE_CREDENTIALS=True,
TEMPLATE_FOLDER='./templates/email'
)

async def send_email_async(subject: str, email_to: str, body: dict):
message = MessageSchema(
subject=subject,
recipients=[email_to],
body=body,
subtype='html',
)

fm = FastMail(conf)
await fm.send_message(message, template_name='email.html')

def send_email_background(background_tasks: BackgroundTasks, subject: str, email_to: str, body: dict):
message = MessageSchema(
subject=subject,
recipients=[email_to],
body=body,
subtype='html',
)
fm = FastMail(conf)
background_tasks.add_task(
fm.send_message, message, template_name='email.html')

In this example, there are two functions, one sends the email asynchronously (or like a normal function) and the other sends the email in the background. You’ll notice the difference after we try to use these functions.

Note that, we generate an HTML email using Jinja2 templating engine. So let’s create an HTML file. First, make a templates folder and create an HTML file named email.html . This file is used on the connection configuration (TEMPLATE_FOLDER).

Like any HTML file using Jinja2 engine, we can provide dynamic data in there and Jinja2 will take care of how it will be rendered. We can access it using body.property pattern.

Note in here we used inline CSS, just like the official documentation of FastAPI-MAIL suggests us.

In sending HTML emails, the CSS expected by mail servers -outlook, google, etc- must be inline CSS.

Create the path operations to send the email.

@app.get('/send-email/asynchronous')
async def send_email_asynchronous():
await send_email_async('Hello World','someemail@gmail.com',
{'title': 'Hello World', 'name': 'John Doe'})
return 'Success'
@app.get('/send-email/backgroundtasks')
def send_email_backgroundtasks(background_tasks: BackgroundTasks):
send_email_background(background_tasks, 'Hello World',
'someemail@gmail.com', {'title': 'Hello World', 'name': 'John Doe'})
return 'Success'

Save all the files, and the server will reload. Now, refresh the documentation page.

You’ll see two new endpoints, namely, /send-email/asynchronous and /send-email/backgroundtasks . Try both endpoints to see the difference.

When you are calling the server using asynchronous, you’ll see a loading indicator in the documentation, because the application needs time to send the email. But if you use background task, the client doesn't need to wait for the operation to finish. This capability would be useful when we send email or notification to users. Here more about background tasks https://fastapi.tiangolo.com/tutorial/background-tasks/.

This is how the email looks after you send it:

You can find the code for this article here, https://github.com/agusrichard/fastapi-workbook/tree/master/send-email.

I hope this article would be a good resource for you, thank you for reading.

--

--

--

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Recommended from Medium

Primitives and References

Microservices vs. SOA — Is There Any Difference at All?

Prefix Tree Pokédex

10 Things Every Software Developer Should Know to Stay Productive

Visual Studio Code: Show hidden folder

Tricks with forward proxy, HaProxy, Squid and a bit more.

JVM —A high level overview

Seamless API Management for Services in Service Catalog

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
Agus Richard

Agus Richard

I am a Software Engineer and Data Science Enthusiast. Love to learn and write. LinkedIn: https://www.linkedin.com/in/agus-richard/

More from Medium

Concurrency with FastAPI

Towards Excellency: Routing Engine Microservice with Python + Fast API and OR-Tools 🚀

Dockerize your API’s: FastAPI — Part1

5 Advance Features of FastAPI You Should Try