Лимит mailcow 500 писем в час и 10 в минуту: на домен, на ящик и кто должен повторять отправку
В mailcow лимит домена — общий бюджет писем на всех сотрудников, а не квота каждого: при лимите 500 писем в час один человек может забрать 499, оставив коллегам одно письмо. Разбираю, как считаются Rate Limits на домен и ящик, почему письмо с 13 получателями ловит лимит «10 в минуту» с одной попытки, и кто должен повторить отправку после отказа.
Симптом: часть сотрудников не может отправлять письма, хотя лимит на ящик не трогали
Ко мне обратилась компьютерная школа «Терминал-школа» (31 рабочее место) с классической жалобой: методисты жаловались, что рассылки расписаний и напоминаний о занятиях родителям иногда «зависают» — письмо уходит в очередь, а получатель видит его на час-два позже. При этом лимит на ящик в настройках mailcow никто не трогал с момента настройки корпоративной почты при разворачивании сервера. Администратор школы был уверен, что лимит применяется к каждому сотруднику отдельно, и был готов поднимать его точечно тем, кто рассылает больше писем — расписания, счета на оплату, уведомления о закрытии групп.
На деле причина была в другом: домену был выставлен общий Rate Limit 300 писем в 3600 секунд (то есть 300 писем в час), а несколько сотрудников бухгалтерии в конце месяца рассылали акты и счета одновременно с методистами, отправляющими массовые уведомления. Лимит считался не персонально, а суммарно на весь домен — и тот, кто успевал отправить первым, «съедал» большую часть квоты, оставляя остальным лишь единицы писем до конца часового окна.
Проблема усугублялась тем, что жалобы приходили не сразу и не от всех: секретарь, отправляющий по 5–10 писем в день, вообще не замечал лимита, а вот рассылка расписаний по 40–60 адресам родителей регулярно упиралась в потолок именно в те дни, когда бухгалтерия закрывала месяц. Разобраться в этом по логам Postfix было почти невозможно — там видна только цепочка отказов 4.x.x без объяснения причины, а сама причина (общий счётчик домена, а не персональный) находится уже в логике Rspamd, который эти лимиты и считает.
Как в mailcow устроены два уровня Rate Limit: домен и ящик
В mailcow ограничение скорости отправки задаётся в двух местах интерфейса: в настройках домена (Domains → Edit domain → Rate Limit) и в настройках конкретного ящика (Mailboxes → Edit mailbox → Rate Limit). Оба поля задаются как «количество писем» плюс единица времени из выпадающего списка (в секунду, минуту, час или день) — например, 500 писем в час. Ключевой момент, который путает администраторов: лимит домена не персональный, а общий на всех отправителей этого домена. Если у домена стоит 500/3600, а у 10 сотрудников нет собственных лимитов ящика, все они делят один и тот же счётчик — и один активный отправитель (например, скрипт рассылки или взломанная учётная запись) может исчерпать лимит за минуты, оставив остальных без возможности отправлять письма до конца часового окна.
Индивидуальный лимит ящика имеет приоритет над лимитом домена: если для конкретного сотрудника задан собственный Rate Limit, именно он проверяется первым для его писем, а лимит домена продолжает считать суммарный трафик всех остальных. На практике это даёт рабочую модель: общий лимит домена ставится как защитный потолок на случай компрометации ящика (например, 1000–2000 писем в час на весь домен из 31 рабочего места), а точечные лимиты ящика — на сервисные и рассылочные аккаунты, у которых легитимно высокий трафик, чтобы они не «съедали» общий бюджет у остальных.
На практике при диагностике я никогда не полагаюсь на память администратора о том, «что там стояло по умолчанию» — за годы эксплуатации сервера через интерфейс успевают пройти несколько человек, и то, что казалось дефолтным значением, часто оказывается настройкой, выставленной год назад под другую задачу. Первое, что я делаю в карточке проблемного домена и ящика в mailcow UI, — фиксирую скриншотом текущие цифры лимитов до того, как что-то менять, чтобы был понятен путь назад, если новая настройка окажется хуже прежней.
Почему одно письмо тринадцати адресатам срабатывает как тринадцать
Второй источник путаницы — это то, как Rspamd (именно он считает лимиты в mailcow) трактует «одно письмо». Ratelimit-модуль Rspamd по умолчанию учитывает не количество отправленных сообщений, а количество получателей: письмо с 13 адресатами в копии расходует не одну единицу лимита, а 13 — как если бы отправитель разослал 13 отдельных писем. Это и есть механизм, из-за которого лимит «10 писем в минуту» срабатывает с первой же массовой рассылки родителям целой группы: 13 получателей в одном письме превышают лимит 10 за один проход, хотя счётчик «отправленных писем» в почтовом клиенте показывает единицу.
В настройках bucket у ratelimit-модуля Rspamd (с версии 2.0) есть параметр skip_recipients, который отключает этот множитель по числу получателей и переводит счётчик на честный подсчёт сообщений, а не адресатов. Важная оговорка: в веб-интерфейсе mailcow такого переключателя нет — это правка конфигурации Rspamd (data/conf/rspamd/local.d/ratelimit.conf или override), которую нужно проверять после каждого update.sh. Менять его стоит осознанно: для рассылок по большим спискам (родительские группы, уведомления всей организации) это снимает ложные срабатывания лимита, но одновременно ослабляет защиту от ситуации, когда взломанный ящик рассылает спам по огромным спискам получателей — именно множитель по получателям в первую очередь останавливает такую рассылку.
У каждого bucket в модуле есть capacity (сколько единиц лимита он вмещает единовременно) и rate (скорость восполнения этих единиц со временем) — это классическая модель «маркерной корзины» (token bucket), знакомая всем, кто настраивал шейпинг трафика на сетевом оборудовании. Именно поэтому лимит «10 писем в минуту» — это не жёсткая линия, после которой всё встаёт намертво: единицы лимита постепенно восстанавливаются, и через некоторое время после первого отказа повторная попытка отправки того же письма вполне может пройти успешно, если к тому моменту счётчик частично освободился.
Что происходит технически при превышении лимита и кто должен повторить отправку
Когда лимит исчерпан, mailcow не отбрасывает письмо навсегда — он возвращает временный SMTP-отказ класса 4.x.x (soft reject). Это стандартный сигнал «попробуйте ещё раз чуть позже», а не «письмо отклонено окончательно» (постоянный отказ 5.x.x). На уровне протокола это принципиальная разница: временный отказ обязывает отправляющую сторону — почтовый сервер или почтовый клиент (MUA) — самостоятельно поставить письмо в очередь на повтор и попробовать снова через некоторое время, без вмешательства человека.
Проблема в том, что не все отправители одинаково хорошо обрабатывают soft reject. Обычный почтовый клиент (Outlook, Thunderbird) в связке с сервером — исправно ретраит через встроенную очередь SMTP. А вот интеграции — CRM, скрипты рассылки расписаний, сервисы уведомлений, которые отправляют письма напрямую через SMTP без промежуточной очереди, — часто просто логируют ошибку и не делают повторную попытку. Именно так терялись уведомления в «Терминал-школе»: скрипт рассылки расписаний из внутренней CRM отправлял письма пачкой в конце дня, ловил временный отказ 4.x.x на части адресов и не повторял отправку, считая операцию завершённой.
Отличить временный отказ от постоянного легко даже без специальных инструментов — по первой цифре кода ответа SMTP в логе: 4.x.x значит «повторите позже», 5.x.x значит «письмо отклонено, повторять бесполезно». Если в логах Postfix встречается временный отказ с текстом про ratelimit или too fast, это почти наверняка сработал ratelimit-модуль Rspamd, а не проблема с DNS, DKIM или репутацией отправителя — они, как правило, дают окончательный отказ 5.x.x или другой текст ошибки. Точный код и текст стоит свериться в логе своей версии — формат сообщения rspamd мог измениться между релизами.
Как посчитать правильный лимит для компании на 30–50 рабочих мест
Для домена без выделенных рассылочных сервисов я обычно считаю лимит от пиковой нагрузки конкретного отдела, а не от общего числа сотрудников: важно не «сколько писем шлёт компания в среднем», а сколько шлёт самый активный отправитель в пиковый час — рассылка расписаний, закрытие месяца в бухгалтерии, массовое уведомление всем клиентам. Для «Терминал-школы» пиковым оказался конец месяца, когда бухгалтерия рассылала акты одновременно с методистами, закрывающими группы, — вместе они не превышали 150–180 писем в час даже с учётом получателей в копии. Я выставил лимит домена 400 писем в час — с запасом на рост, но достаточно низкий, чтобы взломанный ящик не разослал тысячи спам-писем за считанные минуты и не попал в чёрные списки.
Отдельный лимит на ящик я ставлю там, где легитимно высокий трафик расходится с остальными: технический ящик для системных уведомлений или интеграции с CRM получает собственный Rate Limit, например 200 писем в час, а остальным сотрудникам оставляю только общий лимит домена. Это разводит «шумного», но легитимного отправителя и защитный потолок для всех остальных — при компрометации обычного личного ящика лимит домена всё ещё не даст разослать спам по всей базе клиентов.
Отдельно проговариваю с клиентом границу «слишком низко» и «слишком высоко». Слишком низкий лимит на 31 рабочее место — это когда обычная рабочая переписка в пиковые часы (утренняя рассылка расписаний, ответы клиентам после обеда) регулярно упирается в потолок, и сотрудники жалуются на задержки каждую неделю, а не раз в квартал. Слишком высокий — это когда лимит фактически не выполняет защитную функцию: если взломанный ящик успевает разослать тысячи писем до того, как сработает лимит, домен компании может попасть в чёрные списки быстрее, чем администратор заметит проблему по алертам watchdog.
Как посмотреть, что лимит сработал, и сбросить счётчики вручную
Состояние всех ratelimit-бакетов Rspamd хранит в Redis, с префиксом ключей RL по умолчанию. Когда нужно снять лимит немедленно — например, после того как вы подняли значение в интерфейсе, а старый счётчик всё ещё «помнит» превышение, — я использую штатную процедуру очистки. В документации mailcow это делается из контейнера redis-mailcow. Нюанс, который в старых инструкциях не учтён: с релиза 2025-01 Redis в mailcow закрыт паролем (переменная REDISPASS в mailcow.conf, она же передаётся в контейнер), поэтому голый redis-cli получит NOAUTH. Я выполняю очистку одной строкой с паролем из окружения контейнера:
docker compose exec redis-mailcow sh -c 'redis-cli -a "$REDISPASS" --no-auth-warning --scan --pattern "RL*" | xargs -r redis-cli -a "$REDISPASS" --no-auth-warning unlink'После очистки перезапускаю Rspamd, чтобы он гарантированно перечитал новые лимиты из конфигурации домена и ящика:
docker compose restart rspamd-mailcowЕсть и более безопасный путь без консоли — веб-интерфейс Rspamd по адресу https://<ваш-хост>/rspamd (пароль к нему задаётся в mailcow UI: System → Configuration → Access → Rspamd UI). Состояние самих бакетов там не показано, зато в истории видно, какие письма получили soft reject и от какого отправителя. Я всегда сначала смотрю туда, чтобы убедиться, что причина именно в ratelimit, а не в чём-то другом — например, не в устаревшей настройке DKIM, SPF и DMARC, из-за которой письма тоже могут задерживаться или откладываться — иначе можно потратить время на сброс счётчика, который вообще ни при чём.
Чек-лист: что проверить перед тем, как менять лимиты в mailcow
Прежде чем менять цифры в интерфейсе, я прохожу по короткому списку, который экономит время и не создаёт новых проблем задним числом:
Из этого списка обычно видно, где реальная причина — либо лимит домена действительно занижен для текущей нагрузки компании, либо один отправитель (рассылка, интеграция, а иногда и скомпрометированный ящик) забирает чужую квоту, и правильное решение — не поднимать общий лимит, а вынести этого отправителя на отдельный лимит ящика.
В «Терминал-школе» в итоге не пришлось поднимать лимит домена — хватило вынести CRM-рассылку расписаний на отдельный технический ящик с собственным Rate Limit 250/3600 и попросить разработчика CRM добавить повтор отправки при получении временного отказа. Бухгалтерия и методисты вернулись на общий лимит домена 400/3600, и с тех пор — уже три месяца — жалоб на задержки писем не было, а при плановой проверке watchdog ни разу не зафиксировал аномального всплеска ratelimit-срабатываний. Проверку лимитов я теперь включаю в регламент обслуживания mailcow — вместе с обновлениями и бэкапами, а не как разовую настройку «поставили и забыли».
- Открыть историю в Rspamd UI и посмотреть, у какого отправителя и на каких письмах сработал ratelimit
- Проверить, кто был активным отправителем в момент превышения — обычная рассылка, интеграция через SMTP или подозрительная активность
- Посчитать реальный пик писем в час с учётом множителя по числу получателей, а не только количество нажатий «отправить»
- Решить: поднять общий лимит домена или вынести «шумного» легитимного отправителя на отдельный лимит ящика
- Проверить, что интеграции и скрипты рассылки умеют повторять отправку при временном отказе 4.x.x, а не считают его финальной ошибкой
- Сбросить ratelimit-ключи в Redis только после того, как новые значения лимитов сохранены в интерфейсе
Частые вопросы
Лимит писем в mailcow действует на весь домен сразу или на каждого сотрудника отдельно?
По умолчанию — на весь домен суммарно: все сотрудники без индивидуального лимита ящика делят один общий счётчик. Персональный лимит ящика, если он задан, имеет приоритет и считается отдельно от лимита домена.
Почему одно письмо с 13 получателями превышает лимит «10 писем в минуту»?
Ratelimit-модуль Rspamd по умолчанию считает не письма, а получателей: 13 адресатов в одном письме расходуют 13 единиц лимита. Отключить это поведение можно параметром skip_recipients в конфигурации Rspamd (в UI mailcow его нет), но это ослабляет защиту от массовой рассылки со взломанного ящика.
Что получает отправитель, когда срабатывает лимит — письмо теряется?
Нет, mailcow возвращает временный отказ SMTP класса 4.x.x (soft reject), а не окончательный отказ 5.x.x. Письмо не потеряно, но повторить отправку должен либо почтовый сервер отправителя, либо программа, отправлявшая письмо напрямую через SMTP.
Как быстро снять лимит, если я уже поднял значение в интерфейсе, а ошибка всё ещё появляется?
Старый счётчик в Redis может ещё действовать до восстановления бакета. Очистите ключи с префиксом RL в контейнере redis-mailcow (с mailcow 2025-01 redis-cli нужен пароль из REDISPASS: redis-cli -a "$REDISPASS") и перезапустите rspamd-mailcow.
Какой лимит домена ставить для компании на 30–50 рабочих мест без своей рассылочной платформы?
Я отталкиваюсь от реального пикового часа, а не от среднего трафика — обычно это конец месяца или массовая рассылка уведомлений. Для такого масштаба на практике достаточно 300–500 писем в час на домен плюс отдельный лимит для технических/рассылочных ящиков.
Стоит ли включать skip_recipients для рассылочного ящика?
Только если этот ящик легитимно и регулярно рассылает письма большим спискам получателей и вы уверены в его защищённости (сложный пароль, 2FA, IP-ограничения). Для обычных пользовательских ящиков я множитель по получателям не отключаю — это одна из линий защиты от массовой рассылки при компрометации.
Источники
- mailcow docs — Watchdog Thresholds — Параметр RATELIMIT_THRESHOLD (по умолчанию 1) — порог уведомления администратора о срабатывании лимита частоты отправки. https://docs.mailcow.email/manual-guides/Watchdog/u_e-watchdog-thresholds/
- Rspamd docs — Ratelimit module — Проверено: устройство bucket (capacity/rate), параметр skip_recipients (отключает множитель по числу получателей), поведение soft reject при исчерпании лимита, хранение состояния в Redis с префиксом ключей RL по умолчанию. https://docs.rspamd.com/modules/ratelimit/
- mailcow docs — Rspamd General Settings — Проверена процедура очистки ratelimit-ключей RL* в контейнере redis-mailcow с последующим docker compose restart rspamd-mailcow; адрес Rspamd UI /rspamd и пароль в System → Configuration → Access → Rspamd UI. https://docs.mailcow.email/manual-guides/Rspamd/u_e-rspamd-general/
- mailcow community — Domain Rate Limits — Обсуждение поведения доменного лимита как общего суммарного бюджета на всех пользователей домена и приоритета индивидуального лимита ящика. https://community.mailcow.email/d/107-domain-rate-limits
- mailcow community — Ratelimited account: 1 message and 13 recipients — Воспроизведённый кейс превышения лимита одним письмом с 13 получателями из-за учёта числа адресатов. https://community.mailcow.email/d/5305-ratelimited-account-runs-into-ratelimit-with-1-message-and-13-recipients
- mailcow.email — 2023-11 Release notes — Проверено исправление 2023-11a: «Fixed Ratelimit forced by global ratelimits» и починка отображения статуса «disabled» для лимитов домена в интерфейсе. https://mailcow.email/posts/2023/release-2023-11/
- mailcow docs — Redis — Проверено: Redis в mailcow защищён паролем REDISPASS из mailcow.conf (с релиза 2025-01), redis-cli требует -a. https://docs.mailcow.email/manual-guides/Redis/u_e-redis/



