Перейти к содержимому
Русский

Отправка через SMTP

Что нужно для подключения

Отправляйте письма из приложения через SMTP с логином и паролем ящика. API-ключ и токен аккаунта для SMTP не подходят.

Создайте активный ящик на подключённом домене и завершите проверку его DNS-записей. Логин — полный адрес, например [email protected]. Пароль — пароль этого ящика, а не почтового аккаунта. В примерах замените адреса своими; пароль вводится скрыто при запуске.

Сервер, порты и шифрование

Используйте mail.adapt-mail.com для любого подключённого домена. На порту 465 TLS включается сразу; на порту 587 сначала выполняется STARTTLS, затем авторизация. Выберите один вариант. Проверку сертификата отключать не нужно.

Адрес From и SMTP-отправитель в примерах совпадают с логином ящика. Имя отправителя можно изменить. Порт 25 предназначен для обмена между почтовыми серверами, для приложения используйте 465 или 587.

SMTP_HOST = "mail.adapt-mail.com"
SMTP_PORT = 465
SMTP_USER = "[email protected]"
SMTP_PASSWORD = "<mailbox-password>"
SMTP_FROM = "[email protected]"
SMTP_FROM_NAME = "Example"
465: implicit TLS
587: STARTTLS

Python: отправка через порт 465

Пример использует только стандартную библиотеку Python 3. Сохраните его в send_mail.py и запустите python3 send_mail.py. Для автоматической отправки получайте пароль из защищённой конфигурации вашего приложения; не сохраняйте его в Git или логах.

import smtplib
import ssl
from getpass import getpass
from email.message import EmailMessage
from email.utils import formataddr, make_msgid, formatdate
username = "[email protected]"
password = getpass("SMTP password: ")
recipient = "[email protected]"
message = EmailMessage()
message["From"] = formataddr(("Example", username))
message["To"] = recipient
message["Subject"] = "SMTP test"
message["Date"] = formatdate(localtime=False, usegmt=True)
message["Message-ID"] = make_msgid(domain=username.split("@")[1])
message.set_content("Hello! This message was sent through Adapt Mail SMTP.")
with smtplib.SMTP_SSL(
"mail.adapt-mail.com", 465, timeout=30,
context=ssl.create_default_context(),
) as smtp:
smtp.login(username, password)
refused = smtp.send_message(
message, from_addr=username, to_addrs=[recipient],
)
print("Rejected recipients:", refused)

Python: подключение через порт 587

Для STARTTLS используйте подготовку письма из предыдущего примера и замените блок with smtplib.SMTP_SSL на следующий. В smtplib.SMTP пароль передаётся только после успешного STARTTLS.

with smtplib.SMTP("mail.adapt-mail.com", 587, timeout=30) as smtp:
smtp.ehlo()
smtp.starttls(context=ssl.create_default_context())
smtp.ehlo()
smtp.login(username, password)
refused = smtp.send_message(
message, from_addr=username, to_addrs=[recipient],
)
print("Rejected recipients:", refused)

HTML и вложения

Добавьте HTML-версию после set_content, а вложение — перед отправкой. Текстовую версию оставьте для клиентов без HTML. Передавайте только доверенный HTML или экранируйте подставляемые данные.

message.add_alternative(
"<p>Hello! This message was sent through <strong>Adapt Mail</strong>.</p>",
subtype="html",
)
with open("document.pdf", "rb") as attachment:
message.add_attachment(
attachment.read(), maintype="application", subtype="pdf",
filename="document.pdf",
)

Результат, лимиты и отправленные

Успешный send_message означает, что SMTP-сервер принял письмо, а не что оно попало во входящие получателя. Словарь refused содержит отклонённых получателей; при отказе всем получателям Python выбросит SMTPRecipientsRefused.

SMTP и API используют общие лимиты одного ящика: до 30 писем за скользящие 60 секунд, до 50 получателей в одном письме и до 1000 получателей за скользящие 24 часа; при включённом повышенном лимите — 5000. Считаются все адресаты To, Cc и Bcc.

Прямая отправка через SMTP сама по себе не сохраняет копию в папке «Отправленные». Это делает почтовый клиент через IMAP; отправка через API Adapt Mail сохраняет копию отдельно.

Ошибки SMTP

535
Авторизация не прошла: проверьте полный адрес, пароль ящика и доступность ящика.
451
Временный отказ, в том числе при превышении лимита отправки. Повторите позже с задержкой.
550 / 5xx
Постоянный отказ: проверьте адреса, права отправителя и текст ответа. Более 50 получателей отклоняются после DATA. Исправьте причину перед повтором.
TLS / timeout
Проверьте имя mail.adapt-mail.com, порт, режим TLS и исходящий доступ с сервера приложения. На 465 используйте SMTP_SSL, на 587 — SMTP с STARTTLS.

Читайте полный ответ SMTP-сервера. Временный отказ повторяйте с задержкой. Если соединение оборвалось после передачи письма и итог неизвестен, не отправляйте его повторно вслепую: в SMTP нет Idempotency-Key, повтор может создать дубликат.