Прежде чем перейти к основной теме, давайте начнем с введения в FastAPI. Что такое FastAPI?

Прямо из официальной документации:

FastAPI - это современный, быстрый (высокопроизводительный) веб-фреймворк для создания API-интерфейсов с Python 3.6+ на основе стандартных подсказок типа Python.

FastAPI приобрел большую популярность в наши дни из-за своей скорости и простоты настройки. Вероятно, все еще остается спорным вопрос, какой из них лучше: FastAPI, Flask (в дополнение к новому Flask 2.0) и Django. Но, на мой взгляд, это относится к нашим вариантам использования. Подробности можно прочитать здесь https://www.section.io/engineering-education/choosing-between-django-flask-and-fastapi/.

Перейдем к основной теме, давайте создадим простое приложение для отправки электронной почты с помощью FastAPI двумя способами, с фоновой задачей и без нее.

До этого

В этой статье мы будем использовать учетную запись Gmail для отправки электронной почты, и чтобы убедиться, что все работает правильно, вам понадобится учетная запись Gmail для этого. Убедитесь, что вы установили Allow less secure apps на On в настройках своей учетной записи Google. Вот как это можно сделать:

  1. Щелкните manage your Google account на значке своей учетной записи (в правом верхнем углу).

2. Перейдите на вкладку безопасности.

3. На этой странице вы найдете раздел, в котором разрешены менее безопасные приложения. (здесь я его включил)

4. Включите эту настройку.

Это не сработает, если в вашем аккаунте включена двухфакторная аутентификация. Вы можете создать отдельную учетную запись или создать пароли для конкретных приложений.

Если ошибки аутентификации по-прежнему возникают, попробуйте следующее:

  1. Показать разблокировку captcha. (Https://accounts.google.com/DisplayUnlockCaptcha)
  2. Включите доступ по протоколу IMAP. (Https://mail.google.com/mail/#settings/fwdandpop)

Создать приложение

Настроить виртуальную среду

Чтобы изолировать среду для этого приложения, мы должны использовать виртуальную среду, в этом случае я буду использовать pipenv для управления виртуальной средой.

pipenv shell

Эта команда создаст оболочку в виртуальной среде и сгенерирует Pipfile. Затем мы можем установить нужные нам зависимости.

pipenv install fastapi fastapi-mail uvicorn python-dotenv

Создайте main.py файл и поместите туда код шаблона.

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)

Чтобы запустить приложение, вы можете набрать команду python main.py. Эта команда запустит сервер, после чего вы сможете просмотреть документацию, созданную FastAPI, перейдя по адресу http: // localhost: 8000 / docs.

Отлично…

Теперь создайте .env файл для хранения конфиденциальных данных.

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>

Создайте файл с именем send_email.py, затем загрузите .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')

У нас есть необходимый импорт и настройки (нам это нужно для конфигурации подключения FastAPI MAIL). Затем напишите конфигурацию подключения и код для отправки электронного письма.

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

В этом примере есть две функции: одна отправляет электронное письмо асинхронно (или как обычная функция), а другая отправляет электронное письмо в фоновом режиме. Вы заметите разницу, когда мы попробуем использовать эти функции.

Обратите внимание, что мы генерируем электронное письмо в формате HTML с помощью механизма шаблонов Jinja2. Итак, давайте создадим HTML-файл. Сначала создайте папку templates и создайте файл HTML с именем email.html. Этот файл используется в конфигурации подключения (TEMPLATE_FOLDER).

Как и любой HTML-файл, использующий движок Jinja2, мы можем предоставить в него динамические данные, и Jinja2 позаботится о том, как они будут отображаться. Мы можем получить к нему доступ, используя шаблон body.property.

Обратите внимание, что здесь мы использовали встроенный CSS, как предлагает нам официальная документация FastAPI-MAIL.

При отправке электронных писем в формате HTML CSS, ожидаемый почтовыми серверами - Outlook, Google и т. Д., - должен быть встроенным CSS.

Создайте операции пути для отправки электронного письма.

@app.get('/send-email/asynchronous')
async def send_email_asynchronous():
    await send_email_async('Hello World','[email protected]',
    {'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',   
    '[email protected]', {'title': 'Hello World', 'name':       'John Doe'})
    return 'Success'

Сохраните все файлы, и сервер перезагрузится. Теперь обновите страницу документации.

Вы увидите две новые конечные точки, а именно /send-email/asynchronous и /send-email/backgroundtasks. Попробуйте обе конечные точки, чтобы увидеть разницу.

Когда вы вызываете сервер в асинхронном режиме, вы увидите индикатор загрузки в документации, потому что приложению требуется время для отправки электронного письма. Но если вы используете фоновую задачу, клиенту не нужно ждать завершения операции. Эта возможность будет полезна, когда мы отправляем пользователям электронную почту или уведомление. Подробнее о фоновых задачах https://fastapi.tiangolo.com/tutorial/background-tasks/.

Вот как выглядит электронное письмо после того, как вы его отправили:

Вы можете найти код для этой статьи здесь, https://github.com/agusrichard/fastapi-workbook/tree/master/send-email.

Надеюсь, эта статья станет для вас хорошим ресурсом, спасибо за чтение.

Использованная литература: