Перейти к содержанию

Flask

Инструкция для приложений на Flask (Python 3.10+). Mailexam подключается как SMTP-сервер через стандартный модуль smtplib; для тестового маршрута достаточно минимального приложения Flask.

Что понадобится

  • Аккаунт Mailexam и проект с SMTP-учётными данными.
  • Python 3.10+ и виртуальное окружение.

Скопируйте из приветственного письма (или кабинета) для вашего проекта:

  • ВАШ_ЛОГИН — SMTP-логин (например, xxxxx);
  • ВАШ_ПАРОЛЬ — SMTP-пароль (уникальная пара к логину);
  • хост — ВАШ_ЛОГИН.mailexam.ru (совпадает с логином).

1. Зависимости

python3 -m venv .venv
source .venv/bin/activate
pip install flask python-dotenv

Файл requirements.txt:

flask>=3.0
python-dotenv>=1.0

2. Переменные окружения

Файл .env в корне проекта (не коммитьте пароли в git):

MAILEXAM_LOGIN=ВАШ_ЛОГИН
MAILEXAM_PASSWORD=ВАШ_ПАРОЛЬ
MAILEXAM_PORT=587
MAIL_FROM=noreply@example.test

Хост собирается из логина: {MAILEXAM_LOGIN}.mailexam.ru.

Адрес отправителя

MAIL_FROM может быть любым тестовым адресом — письмо попадёт в Mailexam, а не реальному получателю.

Альтернативные порты

MAILEXAM_PORT=587
MAILEXAM_PORT=2525
MAILEXAM_PORT=25

В коде для порта 25 не вызывайте starttls() (см. модуль ниже).

3. Модуль отправки почты

# mail.py
import os
import smtplib
from email.message import EmailMessage


def smtp_host() -> str:
    login = os.environ["MAILEXAM_LOGIN"]
    return f"{login}.mailexam.ru"


def send_test(*, to: str, subject: str, body: str) -> None:
    login = os.environ["MAILEXAM_LOGIN"]
    password = os.environ["MAILEXAM_PASSWORD"]
    port = int(os.environ.get("MAILEXAM_PORT", "587"))
    mail_from = os.environ.get("MAIL_FROM", "noreply@example.test")

    msg = EmailMessage()
    msg["From"] = mail_from
    msg["To"] = to
    msg["Subject"] = subject
    msg.set_content(body)

    with smtplib.SMTP(smtp_host(), port, timeout=30) as smtp:
        if port == 587 or port == 2525:
            smtp.starttls()
        smtp.login(login, password)
        smtp.send_message(msg)

4. Маршрут Flask

# app.py
import os

from dotenv import load_dotenv
from flask import Flask, jsonify, request

from mail import send_test

load_dotenv()

app = Flask(__name__)


@app.post("/mail/test")
def mail_test():
    data = request.get_json(force=True, silent=True) or {}
    to = data.get("to", "user@example.test")
    subject = data.get("subject", "Flask + Mailexam")
    body = data.get("body", "Тест Mailexam из Flask")

    send_test(to=to, subject=subject, body=body)
    return jsonify({"status": "ok"})


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000, debug=True)

Запуск и проверка:

python app.py
curl -X POST http://127.0.0.1:5000/mail/test \
  -H 'Content-Type: application/json' \
  -d '{"to":"user@example.test","subject":"Проверка","body":"Привет"}'

Письмо появится в кабинете Mailexam → ваш проект → входящие.

5. Локальная разработка и CI

Среда Рекомендация
local .env с личным проектом Mailexam
CI Секреты MAILEXAM_LOGIN, MAILEXAM_PASSWORD в GitLab CI/CD Variables

Пример для .gitlab-ci.yml:

variables:
  MAILEXAM_LOGIN: $MAILEXAM_LOGIN
  MAILEXAM_PASSWORD: $MAILEXAM_PASSWORD
  MAILEXAM_PORT: "587"
  MAIL_FROM: "noreply@example.test"

После интеграционного теста с отправкой письма проверьте доставку через API Mailexam.

6. Типичные проблемы

Ошибка TLS или подключения

  • Хост должен быть {логин}.mailexam.ru, где {логин} — то же значение, что MAILEXAM_LOGIN из письма.
  • Логин и пароль — пара из письма; не комбинируйте данные разных проектов.
  • Для порта 587 вызывайте smtp.starttls() перед login().

Письмо не в кабинете

  • Убедитесь, что смотрите входящие того же проекта Mailexam.
  • Проверьте логи Flask и traceback при отправке.

Переменные окружения не подхватываются

  • Вызовите load_dotenv() до чтения os.environ.
  • В production передавайте переменные через окружение процесса или секреты CI.

См. также