skeeks / cms-communication-unisender
Unisender Go mailing service driver for skeeks/cms-communication: sending through the API, delivery events by webhook
Package info
github.com/skeeks-cms/cms-communication-unisender
Type:yii2-extension
pkg:composer/skeeks/cms-communication-unisender
Requires
- php: >=8.0
- ext-curl: *
- ext-json: *
- skeeks/cms-communication: ^1.19.6
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-30 12:23:33 UTC
README
Драйвер сервиса рассылок Unisender Go (https://go.unisender.ru) для
skeeks/cms-communication. Письма кампании уходят через API Unisender Go по
одному, каждое со своими метаданными; доставку, отказы, жалобы и отписки
сервис сообщает вебхуком, и CRM записывает их к нужному письму. Всё общее
(кампании, письмо, отписка, стоп-лист, события доставки, отчёт) — в
cms-communication (README, разделы «Рассылки» и «События доставки»); здесь
только протокол Unisender Go (сверено с https://godocs.unisender.ru/web-api-ref).
Через сервис пишем только своей базе с согласием на тему: Unisender Go запрещает базы без согласия, этого требует и 38-ФЗ. Холодные контакты — кампании «Ящики менеджеров».
Установка
composer require skeeks/cms-communication-unisender php yii migrate
Пакет сам регистрирует драйвер unisender, канал кампании «Сервис рассылок
(Unisender Go)», задачи comm.campaign.unisender и comm.unisender.apply
(очередь communication), адрес вебхука POST /~unisender/<id подключения> и
консольную команду unisender.
Как завести Unisender Go
- Зарегистрироваться на https://go.unisender.ru. Сервер аккаунта — в адресе
личного кабинета:
go1.unisender.ruилиgo2.unisender.ru. - Настройки → Домены отправки → «+»: домен, с адресов которого пойдут
письма, и поддомен ссылок. Лучше отдельный поддомен рассылок (так сделано
для skeeks.com:
news.skeeks.com, ссылкиlink.news.skeeks.com): жалобы и отказы рассылок не портят репутацию рабочей почты основного домена, а его SPF не трогается. Поддомен не должен быть занят записью CNAME (у skeeks.commail— CNAME почты Яндекса, рядом с ним TXT не завести). Кабинет покажет DNS-записи, имя@в них — сам поддомен:- SPF: TXT на поддомен
v=spf1 include:spf.unisender.ru ~all(для самого домена — дописатьinclude:spf.unisender.ruв существующуюv=spf1); - DKIM: TXT с селектором из кабинета (у нас
gokey._domainkey.news); ключ копировать целиком, без перепечатывания; - проверочная запись: TXT
unisender-go-validate-hash=…на поддомен; - DMARC: CNAME
_dmarc.<поддомен>из кабинета (без него поддомен берёт DMARC основного домена); - домен ссылок: три NS
uns1/uns2/uns3.unisender.com.(или CNAME из кабинета). Он обязателен, даже если учёт переходов выключен: общий домен ссылок Unisender для аккаунта бывает запрещён, и тогда отправка отвечает «Custom backend domain or tracking domain required for sending». Активируется сам после того, как NS разойдутся: обычно за минуты–часы, по документации сервиса — до 48 часов. Через 30 минут — несколько часов нажать «Проверить» в кабинете: зелёные галочки — домен готов (DKIM-подпись включается в течение часа).
- SPF: TXT на поддомен
- Тариф: бесплатный отправляет до 100 писем в сутки и только на адреса своих подтверждённых доменов; на любые адреса — платный тариф.
- Написать в поддержку Unisender Go и попросить:
- разрешить
track_read = 0иtrack_links = 0(учёт открытий и переходов ведёт CRM, сервис не должен менять ссылки); - «динамическое отключение ссылки отписки» (
skip_unsubscribe): тогда в письме только наша ссылка «Отписаться» и наш заголовокList-Unsubscribe. Сервис может попросить доп. соглашение. Аккаунту SkeekS поддержка 30.10.2026 сразу включила отключение учёта, а отключение отписки обещала после проверки писем — не раньше чем через 2 недели регулярных отправок (это ответ нашему аккаунту, у других условия могут отличаться). Пока не разрешили: в подключении выбрать «Нет» у «Учёт открытий и переходов у Unisender Go выключен», иначе письма не уйдут, и оставить «Нет» у «Своя ссылка отписки». Тогда наша ссылка «Отписаться» в рекламном письме уходит меткой сервиса{{UnsubscribeUrl}}: Unisender Go не добавляет свой блок в конец письма, ссылка ведёт на его страницу отписки, а CRM узнаёт об отписке по вебхуку. Для обычных писем (переписка, не рассылка) — настройка «Отписка в обычных письмах»: «Наша маленькая строка» (по умолчанию — серая «Отписаться от писем» с той же меткой), «Стандартный блок Unisender Go» или «Без отписки» — последнее только после разрешения поддержки, иначе письма не уйдут.
- разрешить
- Аккаунт → Безопасность → API-ключ (или ключ проекта в «Проектах»).
Подключение в CRM
«Настройки» → «Почтовые ящики» → «Добавить»:
- «Адрес» — адрес отправителя на подтверждённом домене (например
news@skeeks.com), «Имя отправителя» — как увидит клиент; - «Подключение к серверу» — «Сервис рассылок Unisender Go — только отправка»; «API-ключ» (хранится зашифрованным, в форму не возвращается, пустое поле при правке оставляет сохранённый), «Сервер API»;
- «Ответы клиентов»: в рабочий ящик сотрудника, от чьего имени письмо, или на
«Ответы направлять на» ящика (раздел «Дополнительно» — общий ящик,
например
info@skeeks.com); - «Писем в минуту» (по умолчанию 60) и «Писем в сутки» (0 — без ограничения);
- «Доступ сотрудников»: кому можно отправлять с этого ящика.
«Проверить подключение» спрашивает system/info (аккаунт, отправлено за
период по тарифу) и webhook/list (все страницы): засчитывается только вебхук
https://…/~unisender/<id> именно этого подключения (и этого домена, когда
проверка идёт из админки), с событиями доставки, отказов, жалоб и отписок.
Вебхук
Адрес — https://<сайт CRM>/~unisender/<id подключения>. Поставить его
на боевом сайте CRM (ящик — адрес отправителя или id подключения):
php yii unisender/webhook news@skeeks.com
команда ставит события delivered, soft_bounced, hard_bounced, spam,
unsubscribed, subscribed и блокировки, delivery_info = 1 (причины
отказов), до 10 параллельных вызовов. Вручную в кабинете — те же события и
«подробности доставки». Стенд вебхук не получит: статусы его писем —
php yii unisender/events news@skeeks.com [часов] 1 (выгрузка событий через API).
Подпись: auth — MD5 тела, в котором значение auth заменено на API-ключ.
Тело больше 4 МБ — 413: сначала по Content-Length, затем вход читается не
дальше предела, сжатое тело распаковывается частями и тоже не больше 4 МБ;
неверная подпись — 403. Принятый вызов
записывается как есть (cms_comm_unisender_callback, один раз) и применяется
задачей comm.unisender.apply: задача идёт порциями, пока есть вызовы, а
повтор того же вызова будит её снова (если постановка задачи сорвалась).
Не применённый вызов ждёт 5 минут и повторяется до 5 раз. Запуск, упавший
вместе с процессом, задача повторяет (до 3 попыток), а агент
comm.unisender.apply-all раз в 10 минут будит её для каждого подключения с
необработанными вызовами — даже если новых вебхуков нет. После применения
тело вызова очищается (в нём IP и устройство читателя), остаётся хэш против
повторов. Откат миграции отказывается, пока есть не применённые вызовы
(new или failed).
Событие относится к письму, если его job_id равен provider_ref письма
(номера отправок уникальны в аккаунте сервиса). Письмо с неизвестным исходом
отправки (provider_ref пуст) принимает событие только своей установки
(sx_origin) и своего сайта (sx_site). sx_origin — случайный номер
установки, записанный один раз в файл runtime/unisender-origin корня
приложения (параметр unisenderOriginFile), а не в базу: у стенда с копией
боевой базы свой номер. Событие чужой установки не трогает ни письма, ни
стоп-листа.
Что делает драйвер
- Каждое письмо — отдельный вызов
email/send: получатели из To, CC и BCC с метаданнымиsx_message,sx_site,sx_origin,sx_campaign,sx_recipient,campaign_id(группировка в отчётах Unisender Go), видимые To и CC — заголовками,idempotence_key, файлы и картинки в тексте. - Шаблонизатор сервиса остаётся
simple(сnoneсервис не подставляет свой заголовок Sender: «${_nameFrom}»). Чтобы он не тронул текст людей,{{и}}в HTML уходят сущностями{{(читатель видит те же скобки), в тексте и теме — с невидимым пробелом нулевой ширины между скобками. Метка{{UnsubscribeUrl}}добавляется после этого. - Рекламное письмо (с темой) уходит только контактам с согласием, письмо кампании «Ящики менеджеров» — никогда. И наоборот: если ящик кампании сервиса после запуска переключили на другое подключение, её письма не уходят (канал и задача отправки проверяют это перед каждым письмом).
- Ответы сервиса: адреса из
failed_emails— событие письма (отписан, жаловался, недоступен → стоп-лист), в том числе при отказе всем получателям (ошибка 204), 429 — письмо ждёт в очереди, 5xx и обрыв связи — исход неизвестен, повторно не отправляется. «Отправлено» — только «сервис принял»; «Доставлено» — по событию вебхука. - Unisender Go даёт письму свой Message-ID: ответ клиента находит переписку
по адресу и теме (
MailIngestService).
Тесты
php tests/unisender.php — без сети и без базы сайта: запросы и ответы по
документации, подпись вебхука, повторы, события, стоп-лист, канал кампании,
выгрузка событий.