Отправка email из Python через smtplib

Финальный шаг многих пайплайнов — разослать результат по почте. Встроенные модули smtplib и email отправляют письма программно, а пароль при этом берётся из переменной окружения.
Суть: email.message собирает письмо (от, кому, тема, тело), smtplib подключается к SMTP-серверу и отправляет. Пароль — только из окружения, никогда в коде.

Отчёт посчитан, документ собран — теперь его надо доставить. Python шлёт почту встроенными средствами: модуль email конструирует само письмо, а smtplib отправляет его через SMTP — протокол отправки почты. Установка SMTP-сервера, порт, шифрование TLS — всё это пара строк настройки.

Сборку самого письма (заголовки, тело) можно полностью отработать в браузере: модуль email.message входит в stdlib и доступен в Pyodide. Соберём письмо и посмотрим на его «сырой» вид.

Попробуй сам ▶

from email.message import EmailMessage

msg = EmailMessage()
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
msg['Subject'] = 'Отчёт о продажах за 22.06.2026'
msg.set_content('''Здравствуйте!

Во вложении дневной отчёт.
Итоговая выручка: 184 200 руб.

-- Автоматическая рассылка''')

# Так письмо выглядит на проводе (заголовки + тело)
print(msg.as_string()[:300])
print('...')
print('Тема:', msg['Subject'])

Объект EmailMessage сам формирует корректные заголовки и кодировку — вам не нужно вручную собирать MIME. Метод set_content задаёт текстовое тело. Отправка через SMTP трогает сеть и пароль, поэтому показана как нерабочая в браузере врезка.

import os, smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
msg['Subject'] = 'Отчёт о продажах'
msg.set_content('Во вложении дневной отчёт.')

# Пароль — из переменной окружения, НЕ в коде!
password = os.environ['EMAIL_PASSWORD']
with smtplib.SMTP_SSL('smtp.company.ru', 465) as server:
    server.login('[email protected]', password)
    server.send_message(msg)
print('Письмо отправлено')
ПУТЬ ПИСЬМА

  данные отчёта
      |  EmailMessage (From/To/Subject/тело)
      v
  готовое письмо
      |  smtplib + login (пароль из окружения)
      v
  SMTP-сервер  --TLS-->  почта получателя

  os.environ['EMAIL_PASSWORD']  <- секрет вне кода

Важная практическая деталь — почтовые провайдеры обычно не дают слать письма под вашим обычным паролем. Вместо него заводят пароль приложения (app password) — отдельный ключ, выданный специально для скриптов, который можно в любой момент отозвать, не меняя основной пароль аккаунта. Это и безопаснее, и обязательно при включённой двухфакторной аутентификации. Получают такой пароль в настройках безопасности почты и кладут — как и любой секрет — в переменную окружения. Если письма «не уходят» с ошибкой авторизации, причина почти всегда в этом: сервис ждёт пароль приложения, а не обычный.

Как работает под капотом

SMTP — это текстовый протокол: ваш скрипт ведёт со сервером диалог из команд (HELO, AUTH, MAIL FROM, DATA). smtplib прячет эти детали за методами. Обёртка SMTP_SSL сразу устанавливает шифрованное соединение, поэтому логин и письмо не идут по сети открытым текстом.

Чтение пароля через os.environ['EMAIL_PASSWORD'] — не стилистическая прихоть, а требование безопасности. Пароль в коде попадёт в git и станет виден всем. Переменная окружения задаётся вне кода (в настройках сервера или файле .env), поэтому секрет не утекает в репозиторий. Это та же логика, что и в уроке про SECRET_KEY.

Частые ошибки

  • Хардкодить пароль в скрипте. Он утечёт в git. Только переменные окружения или секрет-хранилище.
  • Путать порты и режимы. 465 — SSL сразу, 587 — STARTTLS после подключения. Несовпадение — и соединение висит.
  • Слать без обработки ошибок. Сеть ненадёжна; оборачивайте отправку в try и логируйте сбои.

Best practices

  • Секреты — всегда из окружения, никогда в исходниках.
  • Используйте шифрованное соединение (SSL/TLS) для логина.
  • Для массовой рассылки делайте паузы и обрабатывайте отказы, чтобы не попасть в спам-лимиты.

Итоги. smtplib и email отправляют почту из Python: соберите письмо, подключитесь по SSL, возьмите пароль из окружения. Безопасность секрета — главное правило. Дальше прикрепим к письму файлы-вложения.

Проверьте себя
1. Откуда правильно брать пароль для отправки почты?
AЗаписать прямо в коде скрипта
BИз переменной окружения, например os.environ['EMAIL_PASSWORD']
CИз имени файла
DЗапрашивать у пользователя каждый раз
2. Чем удобен класс EmailMessage из модуля email?
AОн отправляет письмо без SMTP
BОн сам формирует корректные заголовки и кодировку письма
CОн шифрует тело письма
DОн заменяет smtplib