Deliverability checklist
This guide is in Russian; an English version is pending.
Что настроить, чтобы письма доходили до входящих, а не в спам. Нормативные источники: требуемые записи и их проверка — docs/spec/10-dns-adapters.md, «Требуемые записи» и «Верификация»; сетевые требования — docs/spec/13-deployment.md, «Сетевые требования для direct-доставки»; заголовки, DKIM и транспорты — docs/spec/06-delivery.md. Развёртывание — руководство.
Обозначения, как в docs/spec/10-dns-adapters.md: D — домен отправки (адрес From), B — bounce-поддомен (по умолчанию bounce.D, домен MAIL FROM), S — DKIM-селектор (по умолчанию pw1), H — хост web.public_url, T — tracking host (если задан).
1. Исходящие адреса (транспорт direct)
- Исходящий TCP 25 с узлов доставки открыт у облачного провайдера (по умолчанию его часто блокируют — заявка на снятие).
- У каждого адреса каждого пула (
[smtp.outbound.pools.<name>]) естьhostname; PTR адреса →hostname, A/AAAAhostname→ адрес (forward-confirmed reverse DNS). PTR ставит владелец адреса — хостер или облако; Postwind только проверяет.EHLOидёт с этимhostname. - Адрес поднят на интерфейсе узла доставки (или пул из одного адреса за NAT:
ip = "",public_ip). - Адреса не в списках блокировок (Spamhaus и др.) — особенно новые адреса облака, у которых была чужая история.
- Проверка
ptrдомена отправки —ok. Неokдаётwarning, а неfailed: домен станетverified, но Gmail и Microsoft отклоняют письма без PTR; предупреждение видно вchecksи в preflight кампании.
2. Требуемые DNS-записи домена отправки
Postwind считает набор записей сам по конфигу узла (web.public_url, пул домена, spf_include relay):
- API:
GET /api/v1/projects/{project_id}/domains/{domain_id}/records(иrequired_records[]в ответе на создание домена); - CLI на узле:
postwind domain records <домен>— записи по строке, поля через табуляцию, для ручного ввода у провайдера (docs/spec/13-deployment.md, «postwind domain records»); - Porkbun:
POST .../domains/{domain_id}/dns/applyставит их сам (dns_provider = porkbun).
| Запись | Имя | Содержание | Проверка |
|---|---|---|---|
| TXT (SPF) | B |
v=spf1 ip4:<адрес пула> ... [include:<spf_include relay>] -all |
spf_bounce |
| MX | B |
10 H |
mx_bounce |
| TXT (DKIM) | S._domainkey.D |
v=DKIM1; k=rsa; p=<публичный ключ> |
dkim |
| TXT (DMARC) | _dmarc.D |
v=DMARC1; p=none; rua=mailto:dmarc@D — только если записи ещё нет |
dmarc |
| CNAME | T |
H |
tracking_cname (и tracking_tls при web.tls.mode = acme) |
| PTR | каждый адрес пула | hostname адреса |
ptr (warning) |
- Записи внесены;
POST .../domains/{domain_id}/verify— доменverified. Кампанию запускает толькоverified-домен; узлы доставки перепроверяют его каждыеdns.recheck_interval_hours(по умолчанию 6 h), и регресс блокирует новые запуски (docs/spec/10-dns-adapters.md, «Перепроверка по расписанию»). - После смены пула домена (
PATCH ... ip_pool) илиtracking_host— новые записи и сноваverify: домен возвращается вpending.
SPF
- SPF проверяется для домена
MAIL FROM, то естьB, а неD: Postwind шлёт с VERP-адресаbounce+<token>@B. Запись на корнеDPostwind не трогает и не требует. - Одна запись
v=spf1наB(две —mismatch, RFC 7208 разрешает одну); лишние механизмы допустимы. НаBуже есть TXT, не начинающаяся сv=spf1, —conflict, Postwind её не перезаписывает. - Каждый адрес пула домена — свой
ip4:/ip6:; для адреса за NAT — егоpublic_ip. - Relay с
spf_include(relays.<name>.spf_include, напримерamazonses.com) добавляетinclude:для каждого такого relay конфига — relay передаёт письмо с тем жеMAIL FROM, поэтому его серверы должны быть в SPFB. Следите за пределом 10 DNS-запросов SPF (каждыйinclude:их тратит).
DKIM
- Запись
S._domainkey.Dс ключом, который Postwind сгенерировал для домена (RSA 2048,rsa-sha256,relaxed/relaxed,docs/spec/06-delivery.md, «Сборка письма»). Длинную TXT провайдер делит на строки сам; проверка склеивает их. -
smtp.outbound.dkim_ed25519 = true— вторая запись с другим селектором (ed25519). - Relay с
sign_dkim = true(по умолчанию): письмо подписывает Postwind ключом вашего домена; у relay свою подпись можно не включать.sign_dkim = false— письмо уходит без подписи Postwind.
DMARC
- Запись
_dmarc.Dесть. Postwind создаётp=noneтолько если записи нет, и никогда её не меняет. Выравнивание проходит в relaxed-режиме:From—D,MAIL FROMи DKIM — поддоменBи доменD. - Отчёты
ruaкто-то читает. После нескольких недель чистых отчётов —p=quarantine, затемp=reject. Gmail и Yahoo требуют DMARC от массовых отправителей (от 5 000 писем в день).
MX bounce и входящий SMTP
-
B MX 10 H, и TCP 25 на адресеHдоходит до подсервисаsmtp.inbound(руководство, «Входящий SMTP»). Без этого отказы после приёма (DSN) и жалобы ARF не приходят, адреса не подавляются, репутация падает.
Tracking host
-
T CNAME H; приweb.tls.mode = acmePostwind сам выпускает сертификат дляT— проверкаtracking_tlsпредупреждает, если его нет или он кончается раньше чем через 14 дней. При TLS на Ingress добавьтеTв хосты и сертификат Ingress.
3. Отписка и жалобы
- Ничего настраивать не нужно: каждое письмо кампании несёт
List-Unsubscribe(ссылка one-click и mailto наunsubscribe@B) иList-Unsubscribe-Post: List-Unsubscribe=One-Click(docs/spec/06-delivery.md, «Сборка письма»). Нужны работающиеweb.public_url(HTTPS) и входящий SMTP. - Жалобы ARF приходят на
fbl@B/abuse@B: подключите feedback loop провайдеров, где он есть (например, Yahoo CFL, Microsoft JMRP), с адресом наB. - Доля жалоб ниже 0,3 % (порог Gmail и Yahoo), лучше ниже 0,1 %. Hard bounce и жалоба подавляют адрес автоматически.
4. Прогрев IP
Новый адрес без истории получает низкие лимиты и спам-папку при резком объёме. В v1 прогрев ручной (docs/spec/13-deployment.md, «Сетевые требования для direct-доставки»): лимиты в конфиге, поднимаются вручную.
- Лимиты на крупных получателей —
[smtp.outbound.domain_limits."<домен>"]:messages_per_minuteиmax_connectionsна пару (исходящий адрес, домен получателя). Два адреса в пуле — двойной суммарный лимит. В Helm:config.smtp.outbound.domain_limits(пример —examples/single-node.yaml). - Скорость кампании —
throttle_per_hourкампании (docs/spec/04-domain-model.md, «Campaign»). - Ориентир (не норма; следите за отказами и жалобами и замедляйтесь при росте): первые дни — сотни писем в день на адрес самым вовлечённым подписчикам; затем примерно удвоение объёма каждые 1–3 дня, пока не выйдете на рабочий объём за 4–8 недель. Пример для
gmail.comна одном адресе: неделя 1 —messages_per_minute = 2, неделя 2 —10, неделя 3 —50, далее — по показателям. - Ответ 4xx с текстом про скорость (
rate limit,too many,throttl, …) Postwind сам замедляет: скорость пары делится на два на 10 минут (docs/spec/06-delivery.md, «Адаптер direct»). Частые такие ответы — знак, что лимит в конфиге выше, чем позволяет репутация. - Наблюдение: Google Postmaster Tools (домен
D), Microsoft SNDS (адреса), статистика Postwind по доменам получателей (GET .../stats/domains), событияdelivery.bounced,complaint.received.
5. Relay вместо direct
Если своих чистых адресов нет, исходящий 25 не открыть или PTR не поставить — шлите через relay (Amazon SES, Postmark, свой Postfix и т. п.): репутацией адресов занимается провайдер (docs/spec/06-delivery.md, «Адаптер relay»).
- Секция
[relays.<name>]:host,port,tls(starttlsилиimplicit; учётные данные сtls = "none"— ошибка конфига),usernameи пароль (в Helm —secrets.relayPasswords),spf_includeпровайдера,sign_dkim = true. - Выбор транспорта:
delivery.default_transport = "relay:<name>"для всей установки,settings.transportпроекта илиtransport_overrideкампании.directи relay можно сочетать: SPFBтогда содержит оба механизма. - Записи DKIM, DMARC и MX bounce те же: письмо по-прежнему от вашего домена с VERP
MAIL FROMнаB, отказы приходят на входящий SMTP Postwind. - Лимиты отправки провайдера (квоты SES и т. п.) —
relays.<name>.max_connectionsиthrottle_per_hourкампаний.
Copied from Postwind docs/ops/deliverability-checklist.md at commit a19b2e4.