Автоответчик mailcow отвечает на основной адрес, но молчит на catch-all: почему и как исправить
Сотрудник в отпуске поставил автоответ, письма на его личный адрес получают ответ, а те же письма на catch-all-ящик компании — тишина. Это не баг и не сломанный Sieve: с 21 июля 2021 года mailcow сознательно проверяет получателя перед vacation-ответом, и catch-all эту проверку не проходит по умолчанию. Разбираю механику и то, как включить ответ адресно, не открывая компанию для backscatter-спама.
Симптом: одному адресу отвечает, другому — нет
Классическая картина: в корпоративной почте на mailcow сотрудник уходит в отпуск, ставит vacation-автоответ через веб-почту SOGo, всё работает — письма на его личный ящик ivanov@domain.ru получают автоматический ответ мгновенно. Но у компании есть общий адрес info@domain.ru, реализованный как catch-all (все письма на несуществующие адреса домена сваливаются в один ящик), и на него тот же самый автоответ включён, но молчит. Отправитель пишет — ответа нет, хотя письмо доставлено и лежит в ящике.
Первая реакция администратора — грешить на сломанный Sieve-скрипт: полезть в контейнер dovecot, посмотреть, скомпилировался ли .sieve в .svbin, проверить синтаксис. Это тупиковый путь: скрипт компилируется нормально, ошибок в логах Dovecot нет, а vacation просто тихо не срабатывает — без единой строки в error.log, которую можно было бы загуглить.
На деле проблема не в конфигурации конкретного ящика и не в синтаксисе Sieve, а в том, как Dovecot вообще решает, отвечать ли на письмо. Это решение завязано на параметр, который в mailcow один на весь сервер, и с 2021 года он по умолчанию выключает автоответ именно для писем, у которых получатель не совпадает буквально с адресом ящика — а catch-all по определению принимает письма на адреса, которых в системе официально не существует. Если в компании вообще ещё не настроена серверная фильтрация почты через Sieve, разобраться с логикой vacation-правил стоит заодно с базовыми фильтрами — они используют один и тот же движок.
Почему так: проверка получателя в Sieve vacation и история mailcow
RFC 5230 (раздел 4.5), описывающий Sieve-расширение vacation, прямо требует (MUST NOT): автоответчик не должен отвечать на письмо, если адрес получателя-пользователя не встречается в заголовках To, Cc, Bcc, Resent-To, Resent-Cc или Resent-Bcc. Адрес считается «своим» тремя способами — реализация знает его сама, это конечный envelope-адрес доставки, либо он явно перечислен в параметре :addresses самого vacation-правила.
На catch-all-ящике это условие почти никогда не выполняется естественным образом: письмо адресовано, например, на sales@domain.ru, которого как отдельного ящика не существует, Postfix доставляет его в catch-all-mailbox info@domain.ru по правилам маршрутизации — а в заголовках To: стоит sales@domain.ru, а не info@domain.ru. Формально для Sieve это письмо «не адресовано» владельцу ящика, и по RFC вообще отвечать не положено.
До 21 июля 2021 года mailcow обходил эту проверку глобально: параметр Dovecot sieve_vacation_dont_check_recipient стоял в yes, и vacation отвечал вообще на любое письмо независимо от получателя — в том числе на catch-all. Проект сознательно сменил значение на no по умолчанию и вынес это отдельной страницей в документацию, потому что глобальный обход проверки получателя — это готовый механизм backscatter: спамер шлёт письма на случайные несуществующие адреса домена (в том числе с поддельным From: реального человека), catch-all их принимает, а автоответчик безусловно отвечает на этот поддельный адрес — компания начинает рассылать спам-эхо по всему интернету от своего имени.
Важно понимать, что это изменение не привязано к конкретной версии mailcow как к разовому патчу — это смена поведения по умолчанию для новых установок и для тех, кто явно не переопределял параметр вручную. Если администратор никогда не переопределял этот параметр руками (в mailcow для этого служит data/conf/dovecot/extra.conf), значение сейчас no: штатный dovecot.conf приходит из репозитория и обновляется вместе с update.sh, и молчание на catch-all — ожидаемое поведение системы, а не деградация после обновления. Если же сервер живёт с 2019–2020 года и его кто-то «чинил» вручную, стоит явно проверить текущее значение командой docker compose exec dovecot-mailcow doveconf -n | grep dont_check_recipient, а не полагаться на предположение.
Как включить ответ на catch-all без побочных эффектов
Правильный путь после смены дефолта в 2021 году — не возвращать глобальный обход, а явно перечислить в самом vacation-правиле дополнительные адреса, которые тоже считаются «своими» для этого ящика — это ровно механизм :addresses из RFC 5230. В mailcow это делается через веб-почту: в SOGo — раздел настроек почты с автоответчиком (Preferences → Mail → Vacation) — есть поле для дополнительных адресов, на которые тоже нужно реагировать.
Для catch-all-ящика туда стоит вписывать не абстрактный список, а конкретные адреса, которые реально важны бизнесу и на которые вы готовы отвечать автоматически: sales@domain.ru, info@domain.ru, возможно ещё один-два адреса из старых визиток и форм на сайте. Каждый добавленный адрес — это явное решение «да, на письма сюда автоответ можно слать», а не слепой обход защиты для всего домена сразу.
Важный нюанс про интервал: параметр :days определяет период, за который отправителю не шлют повторный vacation-ответ. По RFC 5230 без :days действует 7 дней либо больший минимум сервера, но в mailcow Dovecot собран с расширением vacation-seconds, и в штатном data/conf/dovecot/dovecot.conf стоит sieve_vacation_default_period = 60s (минимум — 5s). SOGo обычно пишет :days в правило явно из своего поля интервала, а вот в самописном Sieve-скрипте без :days повтор уйдёт уже через минуту. Для catch-all-ящика, который получает рассылки-боты и автоматизированные системы чаще, чем личная почта, это единственное, что защищает от бесконечного пинг-понга автоответов; уменьшать это значение вручную без веской причины я не рекомендую.
Ещё один момент, который упускают почти всегда: список дополнительных адресов — это не разовая настройка «включил и забыл». Когда компания заводит новый алиас (например, отдел добавляет partners@domain.ru для внешних контактов), про него часто вспоминают только через неделю, когда первый партнёр жалуется, что писал и не получил даже автоматического подтверждения. Я рекомендую держать короткий регламент: любой новый алиас, который заводят на catch-all и на который планируют присылать автоответ, сразу же добавляется в список дополнительных адресов того же vacation-правила — это одна строка в чек-листе выдачи нового адреса, а не отдельная задача постфактум.
- SOGo → Preferences → Mail → Vacation — включить автоответ
- Добавить в дополнительные адреса каждый конкретный alias catch-all, на который нужен ответ
- Не трогать глобальный sieve_vacation_dont_check_recipient — он должен оставаться no
- :days задать явно (например, 7 дней) — это защита от дублирующихся ответов
Почему не стоит просто вернуть глобальный обход
Соблазн очевиден: дописать в data/conf/dovecot/extra.conf строку sieve_vacation_dont_check_recipient = yes внутри блока plugin { } (в штатном dovecot.conf mailcow этого параметра сейчас вообще нет — действует умолчание Dovecot no), перезапустить dovecot-mailcow и получить рабочий автоответ на catch-all за одну правку. Формально это сработает — и именно поэтому так было по умолчанию до июля 2021 года. Но это решение действует на весь почтовый сервер сразу, для всех доменов и всех ящиков, а не только для одного catch-all, который вы хотели починить.
На практике это означает: любое письмо с поддельным From:, отправленное на любой несуществующий адрес любого домена на этом сервере, если у соответствующего catch-all-ящика включён vacation, получит автоматический ответ. Это ровно тот сценарий backscatter, из-за которого IP сервера имеет все шансы попасть в DNSBL — включая Spamhaus, после чего проблемы с доставкой получит уже вся компания.
Я в своей практике глобальный флаг не трогаю ни на одном клиентском сервере — только точечные :addresses в конкретных vacation-правилах, которые нужны бизнесу. Это чуть дольше на старте (нужно явно перечислить адреса, а не поставить один флаг), но избавляет от риска, что через полгода сервер окажется в блок-листах из-за автоответов на спам-рассылки, которые никто не отслеживал. Похожая логика «не давать глобальный обход ради локального удобства» стояла за разбором уязвимости в шаблоне mailcow, которая тоже открывала доступ шире, чем требовалось конкретной задаче.
Кейс: «СвязьЛиния», общий ящик поддержки на catch-all
Клиент — телекоммуникационный провайдер «СвязьЛиния», 46 рабочих мест. Похожую задачу — перевод компании на собственный mailcow с публичной почты — мы решали и для другого клиента, но здесь сервер уже был развёрнут, и требовалось только донастроить автоответ. У «СвязьЛинии» исторически было настроено несколько адресов техподдержки: support@, noc@, abuse@ — все они собирались в один catch-all-ящик catchall@domain.ru, который читает дежурная смена. При переходе на новый регламент захотели включить автоответ «заявка принята, среднее время реакции — 20 минут» на все три адреса разом, но настроили vacation только на самом catch-all-ящике и не понимали, почему письма на support@ молчат, а на сам catchall@ (по прямой ссылке, которую никто не использует) — отвечают.
Разбор занял около часа: подняли документацию mailcow по этому конкретному кейсу, проверили дату смены дефолта, убедились, что sieve_vacation_dont_check_recipient на сервере клиента стоит no (как и должно быть — сервер разворачивался в 2024 году, историческое значение yes там никогда не стояло). Дальше — просто добавили support@domain.ru, noc@domain.ru, abuse@domain.ru в поле дополнительных адресов vacation-правила catch-all-ящика через SOGo.
После правки автоответ пошёл на все три адреса в течение первого же тестового письма — задержки не было, перезапуск сервисов не потребовался: Sieve-правило пересобирается сразу при сохранении из SOGo. Отдельно предупредил дежурную смену: если понадобится добавить четвёртый адрес техподдержки, это те же два клика в интерфейсе, а не заявка на изменение конфигурации сервера.
Отдельно проговорили с клиентом риск, из-за которого я категорически отказался включать глобальный обход, хотя дежурная смена изначально просила «сделать быстрее». У «СвязьЛинии» как у телеком-провайдера есть публичные формы обратной связи на сайте и десятки внешних интеграций, которые шлют письма на технические адреса компании — это ровно та среда, где боты и спамеры массово перебирают несуществующие адреса на домене. Обход проверки получателя на всём сервере в такой ситуации означает не «автоответ на catch-all заработает», а «сервер начнёт автоматически отвечать на любой спам, адресованный на любой выдуманный адрес домена» — и это первый шаг к попаданию в DNSBL.
Чек-лист: диагностика автоответчика на catch-all за 10 минут
Если автоответ молчит именно на catch-all-адресах, а на именные ящики работает — не тратьте время на пересборку Sieve-скриптов и перезапуск dovecot-mailcow. В 9 случаях из 10 причина ровно в проверке получателя, и лечится она на уровне интерфейса, без правок серверных конфигов.
Порядок действий: убедитесь, что vacation вообще включён на нужном ящике в SOGo; проверьте, что адрес, на который реально приходит письмо (алиас, попадающий в catch-all), внесён в дополнительные адреса этого vacation-правила; убедитесь, что письмо от тестового отправителя не попадает под :days-подавление повторных ответов (если вы уже тестировали пять минут назад — подождите или используйте другой тестовый ящик); и только после этого лезьте в логи Dovecot командой docker compose exec dovecot-mailcow doveadm log errors, если проблема не в этом.
Отдельно зафиксируйте для себя список алиасов, у которых включён vacation на catch-all — на практике таких обычно немного (в проектах, что я вёл, от одного до пяти на компанию), и держать его актуальным вручную проще, чем автоматизировать. При смене состава сотрудников, заводящих новые публичные адреса, эта короткая проверка занимает меньше времени, чем один разбор жалобы клиента на молчащий автоответ.
- Vacation включён на нужном ящике в SOGo — проверить в Preferences → Mail → Vacation
- Реальный адрес доставки (алиас) добавлен в дополнительные адреса vacation-правила
- :days-подавление не мешает — тестовое письмо не дублирует недавнее
- Только после этого — docker compose exec dovecot-mailcow doveadm log errors
- Глобальный sieve_vacation_dont_check_recipient не трогать — оставить no
Частые вопросы
Можно ли настроить автоответ сразу на весь домен, а не перечислять адреса вручную?
Через штатный механизм — нет, и это осознанное ограничение mailcow: перечисление конкретных адресов в :addresses защищает от backscatter. Если адресов много и они меняются часто, проще завести отдельный процесс актуализации списка в SOGo, чем включать глобальный обход.
Автоответ на catch-all работал до обновления mailcow, а после перестал — что случилось?
Скорее всего сервер обновлялся через промежуточную версию, где менялся дефолт sieve_vacation_dont_check_recipient (граница — 21 июля 2021 года), и старое значение yes при обновлении не сохранилось или было сброшено. Проверьте текущее значение и переходите на явные адреса в :addresses, а не возвращайте старое поведение.
Что будет, если не добавить адрес в :addresses, а просто включить vacation на catch-all-ящике?
Vacation формально включён, но Sieve проверит заголовки To/Cc/Bcc письма и не найдёт там адрес, который сервер считает «своим» для этого ящика — ответ не уйдёт. Внешне это выглядит как «автоответчик не работает», хотя правило настроено верно.
Сколько дополнительных адресов можно указать в :addresses для одного ящика?
RFC 5230 не задаёт жёсткого лимита на количество адресов в :addresses, ограничение обычно практическое — удобство сопровождения списка. Для типового catch-all с 3–5 алиасами это не проблема.
Влияет ли :days на то, что автоответ вообще не срабатывает на новый адрес?
Нет, :days влияет только на повторные ответы одному и тому же отправителю в пределах периода (по RFC — 7 дней, в штатном конфиге mailcow без явного :days — 60 секунд) — на первое письмо с нового адреса это ограничение не действует.
Источники
- mailcow docs: Vacation replies for catchall addresses — Описание проблемы, история смены sieve_vacation_dont_check_recipient с yes на no 21 июля 2021 года, рекомендация использовать дополнительные адреса в автоответчике SOGo. https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-catchall_vacation/
- RFC 5230 — Sieve Email Filtering: Vacation Extension — Раздел про :addresses (дополнительные адреса, считающиеся принадлежащими пользователю), требование не отвечать, если получатель не найден в To/Cc/Bcc/Resent-*, и правило умолчания :days (7 дней либо больший минимум сервера). https://www.rfc-editor.org/rfc/rfc5230.html
- mailcow community: Send Dovecot Sieve autoresponder emails through Postfix (separate container) — Обсуждение поведения автоответчика и catch-all в реальных инсталляциях mailcow, контекст для проверки, что тема актуальна и обсуждается сообществом. https://community.mailcow.email/d/5087-send-dovecot-sieve-autoresponder-emails-through-postfix-separate-container



