Email-рассылки
Email-рассылка отправляет одну опубликованную версию контента аудитории, давшей согласие, с вашего подтверждённого домена. Откройте раздел Email и перейдите по ссылке Email-рассылки.
Перед первой рассылкой нужен подтверждённый домен отправки, см. Email с вашего домена. Пока домен не подтверждён, письма не отправляются вообще.
Редактор
Редактор рассылки состоит из четырёх шагов.
Письмо и отправитель. Название рассылки (до 160 символов), домен отправки, имя отправителя, адрес для ответа, тема (до 255 символов) и прехедер (до 500 символов). Адрес для ответа указывается «голым», например hello@example.com, без отображаемого имени. Переводы строки в имени отправителя, адресе для ответа, теме и прехедере запрещены: через них возможна подмена заголовков письма.
Контент и предпросмотр. Выберите опубликованную версию email-контента или создайте её из шаблона. Рассылка сохраняет идентификатор документа вместе с точным номером версии: последующая публикация документа не изменит уже запланированную рассылку.
Аудитория и эксперимент. Либо все email-подписчики бота, либо один готовый сегмент. При желании подключите A/B-эксперимент: при планировании рассылка зафиксирует версию эксперимента и будет отчитываться по этому снимку.
Расписание и приватность. Время отправки, режим часового пояса, писем в минуту (от 1 до 10 000) и переключатель сбора открытий. Время отправки указывать необязательно: рассылка без него стартует сразу при запуске.
Есть два режима часового пояса:
- По времени рассылки – один абсолютный момент для всех, посчитанный в часовом поясе рассылки.
- По местному времени получателя – одно и то же время на часах в поясе каждого получателя.
Список поясов фиксированный: Москва, Белград, Лондон, Берлин, Дубай, Алматы, Тбилиси, Ереван, Ташкент, Бангкок, Токио, Нью-Йорк, Лос-Анджелес, UTC.
Перевод часов обрабатывается явно, а не молча:
- редактор не принимает время отправки, которого в этот день не существует в часовом поясе рассылки, и пишет об этом под полем;
- в режиме местного времени получатель, у которого это время на часах в тот день не наступает, попадает в проверку с кодом
nonexistent_local_time, и запуск заблокирован, пока время не изменят; - если время на часах повторяется дважды, для всех берётся более ранний момент.
В режиме получателя человек без пригодного часового пояса исключается, а не получает письмо в произвольный час.
Проверка получателей до отправки
Проверить получателей ничего не отправляет. Она собирает аудиторию по текущему черновику и правилам согласия и отвечает, сколько человек получит рассылку, сколько исключено и почему, а также какие в контенте ошибки и предупреждения.
В ответе используются те же коды, что видно в интерфейсе.
Адрес попадает в исключённые, если:
- его подписка не в состоянии «подписан» – причиной тогда указано само состояние:
unsubscribed,bouncedилиcomplained; - адрес пуст или непригоден (
invalid_email); - такой же нормализованный адрес уже есть в этой рассылке (
duplicate); - включён режим местного времени, а у человека нет часового пояса (
missing_timezone), он не распознан (invalid_timezone) либо такого местного времени в этот день не существует (nonexistent_local_time); - согласие было отозвано между подготовкой списка и попыткой отправки (
no_consent).
Запуск блокируют именно ошибки:
domain_not_verified– домен отправки не подтверждён;content_not_published– выбранной версии контента нет или она не опубликована;audience_not_ready– выбранного сегмента нет или он ещё не пересчитан;experiment_not_ready– связанный эксперимент не запущен либо его текущая версия распределяет не по подписчикам;scheduled_in_past– время отправки уже прошло;nonexistent_local_time– см. выше;empty_audience– рассылку никто не получит;- все ошибки контента из Студии контента, привязанные к полю
content_document_idи к проблемному блоку.
Предупреждения контента приходят там же, плюс одно собственное:
missing_plain_text– в контенте нет читаемого текста, только медиа и кнопки, поэтому текстовая часть письма окажется пустой.
Рассылку можно запустить только при нуле ошибок. Предупреждения запуск не блокируют.
Отправить тестовое письмо отправляет контент рассылки на один уже подтверждённый и не отписавшийся email-контакт этого бота. Строки получателей рассылки при этом не затрагиваются, а произвольный адрес ввести нельзя, так что тест не может испортить запланированную отправку.
Запуск и управление
Запустить можно только рассылку в состоянии «Черновик». Запуск требует явного подтверждения и ревизии, которая сейчас на экране. В этот момент рассылка материализуется: версия контента, отправитель, аудитория, расписание и версия эксперимента фиксируются в неизменяемом снимке отправки, и для каждого подходящего адреса создаётся строка получателя.
После этого рассылку нельзя редактировать. Чтобы что-то изменить, нажмите Создать копию и запустите копию.
Статусы: Черновик, Запланирована, Отправляется, На паузе, Завершена, Отменена, Не удалась, В архиве. Из каких статусов доступны действия:
- Поставить на паузу – из «Запланирована» или «Отправляется».
- Продолжить – из «На паузе», обратно в «Запланирована».
- Отменить – из «Черновик», «Запланирована», «Отправляется» или «На паузе». Тем, кому ещё не отправили, письмо не уйдёт.
- В архив – из «Черновик», «Завершена», «Отменена» или «Не удалась».
Каждое действие управления тоже несёт ожидаемую ревизию, поэтому два оператора не могут незаметно перебить работу друг друга.
Сама отправка идёт с заданной скоростью писем в минуту, выполняется пачками с арендой задания и переживает перезапуск воркера. Получателя с временной ошибкой отправки повторяют с растущей задержкой: начиная с 15 секунд и не больше 15 минут. Отправку, которую провайдер принял, но исход которой не подтверждён, записывают как Статус неизвестен, а не повторяют молча: повтор рисковал бы дублем письма.
Трекинг, приватность и отписка
Каждая отслеживаемая ссылка – пиксель открытия, переход и отписка – это подписанный токен на вашей же установке вида https://<ваш-хост>/e/t/<токен>. Токены подписаны HMAC, ограничены одним ботом, рассылкой и получателем и истекают через 90 дней после отправки. Ключ подписи выводится из секрета почтовых вебхуков установки: без него рассылка не отправится вообще, а не уйдёт с неотслеживаемыми ссылками.
- Отслеживание открытий – это GIF 1×1. Оно необязательно: если выключить «Собирать статистику открытий», пиксель просто не добавляется, а доставка, переходы, жалобы и отписки продолжают считаться. Открытия всегда занижены, объяснение есть в статье Email с вашего домена.
- Отслеживание переходов переписывает только кнопки-ссылки на
https://. Токен перехода несёт адрес назначения, и этот адрес обязан бытьhttps://-ссылкой с хостом и без встроенных учётных данных, поэтому перенаправить его в другое место нельзя. - Токены отписки намеренно не несут ни идентификатора ссылки, ни адреса перехода: отписка – это действие, а действие не должно уметь никуда перенаправлять.
Недействительный, истёкший, чужой или неизвестный токен получает 404 без подробностей, поэтому по токену нельзя разведать существующие рассылки и получателей.
Отписка работает по RFC 8058 в один клик. GET показывает простую HTML-страницу подтверждения без JavaScript, а POST с единственным полем формы List-Unsubscribe=One-Click выполняет отписку. Повторная отписка тем же токеном считается успехом, а не ошибкой: почтовые клиенты предзагружают ссылки, а люди кликают дважды. Отказ записывается и в строку получателя, и в канонический учёт согласий одной транзакцией, поэтому ссылка не может отчитаться об успехе, оставив согласие активным.
Отчёт
Отчёт по рассылке разделяет: Получатели, Исключены, Ожидают, Отправляются, Принято провайдером, Статус неизвестен, Доставлено, Открыто, Переходы, Возвраты, Жалобы, Отписки, Ошибки и Отменены. Переходы показываются по каждой ссылке, а получателей можно листать постранично со статусом и причиной исключения.
Атрибутированная выручка показывается отдельно по каждой модели атрибуции и каждой валюте и никогда не суммируется между ними: разные модели законно приписывают одну конверсию по-разному, а смешанная по валютам сумма не имеет смысла.
Ответы получателей
Входящий маршрут превращает адрес на подтверждённом домене в обращение в поддержку. Локальная часть адреса хранится только в виде необратимого хеша, поэтому сам адрес рядом с маршрутом не сохраняется.
Экрана для маршрутов в панели пока нет. Управляйте ими через API с токеном, у которого есть settings:read / settings:write:
curl -X POST "$BASE_URL/api/bots/$BOT_ID/email/inbound-routes" \
-H "Authorization: Bearer $PAT" -H "Content-Type: application/json" \
-d '{"domain":"mail.example.com","local_part":"support"}'
Локальная часть приводится к нижнему регистру и должна подходить под [a-z0-9][a-z0-9._+-]{0,62}. Домен уже должен быть подтверждён для этого бота, иначе ответ будет 422; повторный тот же адрес – 409. Полный адрес возвращается один раз, при создании: в списке потом виден только домен, потому что локальная часть не хранится. Если в установке не настроен секрет почтовых вебхуков, ответ будет 503 – входящая почта выключена целиком.
Входящее письмо нормализуется до того, как попадёт в диалог:
- отправитель сопоставляется с подписчиком по нормализованному адресу;
In-Reply-ToиReferencesпродолжают существующую переписку, но только если она принадлежит тому же человеку;- цитируемая история вырезается из текста;
- исходное письмо ограничено 8 МиБ, извлечённый текст 256 КиБ, тема 255 символами, а
References32 записями; - сохраняется не больше 5 вложений размером не больше 1 МиБ каждое, по контентному ключу; исполняемые вложения (
.bat,.cmd,.com,.dll,.exe,.msi,.scrи MIME-типы исполняемых файлов) отклоняются; - письмо только в HTML сводится к тексту.
Письмо на неизвестный маршрут принимается и отбрасывается, поэтому опечатка в адресе не превращается в шторм повторов.
Контракт провайдера
Если вы держите собственную установку или пишете адаптер к почтовому провайдеру, вот два публичных эндпоинта, с которыми он общается. Оба проверяют подпись HMAC-SHA256 по сырому телу запроса, в hex, в заголовке X-Signature, на настроенном секрете вебхуков почты. Запрос без подписи, а также любой запрос, если секрет не настроен, отклоняется с 401: эндпоинт закрывается по умолчанию.
События доставки и вовлечения
POST /esp/{provider}/webhook, тело до 1 МиБ:
{
"provider_id": "prv_00000000-0000-0000-0000-000000000000",
"event": "delivered",
"bounce_class": "hard",
"url": "https://example.com/offer",
"event_id": "evt_0000000001",
"tag": "email-campaign:11111111-1111-1111-1111-111111111111:22222222-2222-2222-2222-222222222222"
}
Это собственный обобщённый контракт платформы, а не формат какого-то одного провайдера. Ваш адаптер переводит callback провайдера в него.
eventпринимает значенияdelivered,opened,clicked,bounced,complained,unsubscribed. Незнакомое значение сохраняется для разбора и ничего не меняет.bounce_classравенhardилиsoftи имеет смысл только дляbounced.tag– это стабильные метаданные, переданные при отправке, в видеemail-campaign:<id рассылки>:<id подписчика>. Он позволяет найти получателя, если callback пришёл раньше, чем сохранился идентификатор провайдера.
Как события отображаются в состояния:
delivered– письмо и получатель рассылки переходят в «Доставлено»;bouncedсbounce_class: hard– письмо «Возврат», адрес исключается, получатель «Возврат»;bouncedсbounce_class: soft– только запись события. Мягкий возврат говорит о конкретной попытке, а не об адресе, поэтому он никого не исключает и не меняет состояние получателя;complained– записывается жалоба, адрес закрывается навсегда;unsubscribed– согласие отзывается, получатель «Отписан»;opened,clicked– записываются как события, состояние не меняется.
Callback, пришедший не по порядку, не может откатить конечное состояние назад.
Идемпотентность строится на event_id, если провайдер его присылает, иначе на SHA-256 сырого тела. Проверка, эффекты и отметка о приёме пишутся одной транзакцией, сериализованной по паре «бот и ключ», поэтому два одновременных дубля одного события не применятся дважды.
Коды ответа подсказывают адаптеру, что делать:
200– событие понято. Сюда же попадают намеренно проигнорированные события: дубль или неизвестный идентификатор письма, которое эта установка не отправляла. Повтор ничего не изменит.400– некорректное тело или отсутствуетprovider_idлибоevent.401– подпись неверна или отсутствует.413– тело больше лимита.500– временный сбой на нашей стороне. Повторять стоит только этот класс.
Входящая почта
POST /esp/{provider}/inbound, тело до 12 МиБ:
{
"event_id": "in_0000000001",
"raw_mime": "<base64 исходного MIME-письма>"
}
Раскодированный MIME не должен превышать 8 МиБ. 200 с {"created": true|false} означает, что письмо принято (false – это дубль уже записанного event_id), 204 – адрес получателя не совпал ни с одним маршрутом, 400 – конверт или MIME не разобрались, 401 – подпись не сошлась, 413 – тело запроса больше 12 МиБ.
Ни один из эндпоинтов не возвращает учётные данные провайдера, адреса получателей, которых не было в запросе, и локальную часть входящего маршрута. Ошибки трекинга и отписки отвечают 404, не сообщая, какая именно проверка не прошла.
Что делать, если
- Ничего не отправляется, а на карточке домена предупреждение – домен отправки ещё не подтверждён. См. Email с вашего домена.
- «Рассылку пока нельзя запустить» – откройте проверку получателей и устраните все ошибки; одни предупреждения запуск не блокируют.
- Много получателей исключено по причине
missing_timezone– рассылка идёт по местному времени, а у людей нет часового пояса. Переключитесь на время рассылки или заполните поле профиля. - Время отправки не принимается или проверка отдаёт
nonexistent_local_time– такого времени на часах в этот день не существует из-за перевода часов. Выберите другое время. - Открытий подозрительно мало – это ожидаемо и не чинится. Сравнивайте рассылки по переходам.
- События провайдера не приходят – проверьте, что адаптер подписывает ровно сырое тело и что секрет вебхука совпадает; неподписанный callback получает
401.
Что дальше
- Студия контента – подготовка и публикация контента письма.
- Email с вашего домена – DKIM, SPF, DMARC, отписки и возвраты.
- Рассылки – отправка реакции подписчикам мессенджеров.
- Эксперименты и атрибуция – A/B-эксперименты и выручка.