Квоты в почтовом сервере — базовый инструмент управления диском и стабилизации сервиса. В Dovecot это реализовано плагином quota, который умеет считать объём (storage) и количество писем (messages), а также отправлять предупреждения при достижении порогов. Традиционно в документации встречается термин quota2 — это не отдельный плагин, а второй (и последующие) корни квот, позволяющие одновременно применять, например, общий лимит по объёму и отдельный лимит по числу сообщений.
Что именно ограничивает Dovecot и как это отражается на IMAP/LMTP
Квоты работают на уровне хранения: Dovecot видит каждое доставленное или загруженное через IMAP письмо и учитывает его в выбранном бэкенде учёта (Maildir++, dict SQL/redis и т.д.).
- Storage — суммарный объём ящика. Удобно задаётся как
storage=1G, либо в байтах. - Messages — количество писем. Задаётся как
messages=20000и т.п. - IMAP: при переполнении
APPENDи копирование в ящик завершаются ошибкой «Over quota». Клиент, как правило, показывает предупреждение. - LMTP/lda: доставка входящего письма может быть отвергнута кодом уровня 5.x.x (например,
552 5.2.2), если превышен лимит с учётомquota_grace.
Важно:
quota_graceпозволяет задать «запас» сверх лимита (в байтах или процентах), в рамках которого сервер продолжит принимать почту, чтобы у пользователя была возможность почиститься без потери сообщений.
Быстрый старт: включаем плагин и базовые правила
Минимальная конфигурация с Maildir++ и общим лимитом 1 ГБ, при этом корзина и спам не учитываются в квоте:
# /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir
mail_plugins = $mail_plugins quota
# /etc/dovecot/conf.d/20-imap.conf
protocol imap {
mail_plugins = $mail_plugins quota imap_quota
}
# /etc/dovecot/conf.d/90-quota.conf
plugin {
# Основной корень квот: Maildir++ счётчик
quota = maildir:User quota
# Правила (можно несколько):
quota_rule = *:storage=1G
quota_rule2 = Trash:ignore
quota_rule3 = Junk:ignore
# Запас сверх лимита
quota_grace = 10%%
# Сообщение для LMTP/IMAP
quota_exceeded_message = Mailbox quota exceeded. Please delete or archive old messages.
}
После перезапуска Dovecot клиенты увидят IMAP-способность QUOTA, а сервер начнёт учитывать объём ящика.
Зачем нужен второй корень квот (quota2)
Практический кейс: вы хотите одновременно ограничить общий объём хранилища и отдельно — количество писем (или задать отдельный лимит на конкретные папки). Для этого используется второй корень квот — quota2. Он независим от первого и имеет собственные правила.
# /etc/dovecot/conf.d/90-quota.conf (фрагмент)
plugin {
quota = maildir:User quota
quota_rule = *:storage=1G
# Второй корень: считаем количество сообщений
quota2 = count:Message count
quota2_rule = *:messages=20000
}
Такой подход даёт гибкость: пользователю не получится хранить десятки тысяч мелких писем, даже если общий объём ещё не исчерпан, и наоборот.
Переменные правила: считаем/игнорируем папки
На уровне одного корня квот можно точечно регулировать учёт отдельных папок:
ignore— папка не учитывается вовсе (подходит дляTrashиJunk).storage=+100M— увеличить лимит при наличии этой папки (добавочный лимит).messages=1000— задать потолок по количеству для конкретной папки.
Пример: общее хранилище 1 ГБ, но для Archive разрешаем дополнительно 200 МБ сверх общего. Для корзины и спама учёт отключён:
plugin {
quota = maildir:User quota
quota_rule = *:storage=1G
quota_rule2 = Archive:storage=+200M
quota_rule3 = Trash:ignore
quota_rule4 = Junk:ignore
}
Бэкенды квот: Maildir++ vs dict (SQL/ки)
По умолчанию Dovecot может вести учёт локально (Maildir++), записывая состояние в файловые структуры ящика. Это просто и надёжно для одиночного сервера. Если у вас несколько фронтендов или требуется централизованная статистика, используйте dict с SQL.
Maildir++ (локально)
Плюсы: не требует БД, не чувствителен к временным сбоям сети. Минусы: сложнее централизованно мониторить, возможны расхождения после офлайн-чисток — решается doveadm quota recalc.
Dict SQL (централизованно)
Идея: Dovecot считает и пишет значения в БД через сервис dict. Удобно для кластеров и общих дешбордов.
# /etc/dovecot/conf.d/10-master.conf (фрагмент)
service dict {
unix_listener dict {
mode = 0600
user = dovecot
group = dovecot
}
}
# /etc/dovecot/dovecot-dict-sql.conf.ext (пример MySQL)
driver = mysql
connect = host=127.0.0.1 dbname=maildb user=mail password=secret
# Пример схемы (создайте таблицу заранее):
# CREATE TABLE quota (
# username VARCHAR(255) PRIMARY KEY,
# bytes BIGINT NOT NULL,
# messages BIGINT NOT NULL
# );
map {
pattern = priv/quota/storage
table = quota
username_field = username
value_field = bytes
}
map {
pattern = priv/quota/messages
table = quota
username_field = username
value_field = messages
}
# /etc/dovecot/conf.d/90-quota.conf
plugin {
quota = dict:User quota::proxy::quotadict
quota_rule = *:storage=1G
}
dict {
quotadict = sql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
Если вы переходите с Maildir++ на dict, после включения сделайте пересчёт:
doveadm quota recalc -A
Если дополнительно ограничиваете диск на уровне ФС, пригодится материал Проектные квоты ext4/XFS и оповещения.

Предупреждения пользователям: quota_warning на 80–100%
Чтобы не доводить до отказа в доставке, отправляйте уведомления при приближении к лимиту. В Dovecot это делает механизм quota_warning, вызывая внешнюю команду при достижении порогов.
# /etc/dovecot/conf.d/90-quota.conf (фрагмент)
plugin {
quota_warning = storage=80%% quota-warning 80 %%u
quota_warning2 = storage=90%% quota-warning 90 %%u
quota_warning3 = storage=95%% quota-warning 95 %%u
quota_warning4 = storage=100%% quota-warning 100 %%u
}
# /etc/dovecot/conf.d/10-master.conf (фрагмент)
service quota-warning {
executable = script /usr/local/bin/quota-warning.sh
user = dovecot
group = dovecot
}
Пример скрипта, который отправляет письмо пользователю. Он получает два параметра: процент и логин.
# /usr/local/bin/quota-warning.sh
#!/bin/sh
PERCENT="${1}"
USER="${2}"
HOSTNAME=$(hostname -f 2>/dev/null || hostname)
/usr/sbin/sendmail -t <<EOF
From: postmaster@${HOSTNAME}
To: ${USER}
Subject: Mailbox usage ${PERCENT}%
Content-Type: text/plain; charset=UTF-8
Ваш почтовый ящик использует ${PERCENT}% от выделенной квоты.
Рекомендуем:
- удалить старые или большие письма (вложений);
- очистить папки Trash/Junk;
- перенести переписку в локный архив.
Если ящик достиг 100%, входящая почта может не доставляться.
--
Автоматическое уведомление Dovecot
EOF
Сделайте скрипт исполняемым и перезапустите Dovecot:
chmod +x /usr/local/bin/quota-warning.sh
systemctl reload dovecot
Интеграция с MTA: моментальная проверка квоты до приёма письма
Чтобы не принимать в очередь письма, которые всё равно не смогут быть доставлены из-за квоты, используйте сервис quota-status (политика). Он мгновенно отвечает MTA, стоит ли принимать письмо. Пример для Postfix:
# /etc/dovecot/conf.d/10-master.conf (фрагмент)
service quota-status {
executable = quota-status -p postfix
client_limit = 1
inet_listener {
address = 127.0.0.1
port = 12340
}
}
# /etc/dovecot/conf.d/90-quota.conf (фрагмент)
plugin {
quota_status_success = DUNNO
quota_status_nouser = DUNNO
quota_status_overquota = 552 5.2.2 Mailbox is full
}
Со стороны Postfix добавьте проверку сервиса политики в цепочку ограничений на этапе RCPT TO. Это снизит нагрузку на очередь и ускорит отказ в случае переполнения.
Чистка при переполнении: стратегия «мягкая автоматизация»
Автоматическая чистка — тонкий момент: агрессивное удаление может привести к потере важных писем. Рекомендуется комбинировать щадящие правила и видимый пользователю отчёт.
Безопасный минимум
- Удалять письма в
Junkстарше 30 дней. - Удалять письма в
Trashстарше 14 дней. - Не трогать
INBOXи произвольные папки без явного согласования.
Скрипт «чистильщик», который можно вызывать и из quota_warning на 100%, и по cron. Он чистит только явно указанные папки и публикует краткий отчёт в системный журнал.
# /usr/local/bin/clean-overquota.sh
#!/bin/sh
USER="${1}"
LOGTAG="dovecot-clean"
# Чистим спам и корзину деликатно
/usr/bin/doveadm expunge -u "${USER}" mailbox Junk savedbefore 30d
/usr/bin/doveadm expunge -u "${USER}" mailbox Trash savedbefore 14d
# Пересчёт квоты после чистки
/usr/bin/doveadm quota recalc -u "${USER}"
# Краткий отчёт в журнал
VSIZE=$(/usr/bin/doveadm quota get -u "${USER}" | awk '/User quota/ {print $5}')
logger -t "${LOGTAG}" "${USER} cleaned; vsize=${VSIZE}"
Интеграция с quota_warning на 100% (последней ступенью):
# /etc/dovecot/conf.d/90-quota.conf (фрагмент)
plugin {
quota_warning4 = storage=100%% quota-warning 100 %%u
}
# /usr/local/bin/quota-warning.sh (фрагмент)
if [ "${PERCENT}" = "100" ]; then
/usr/local/bin/clean-overquota.sh "${USER}" &
fi
Обратите внимание: чистку лучше выполнять асинхронно, чтобы не блокировать рабочие процессы Dovecot.
Поиск «тяжёлых» папок и писем
Для анализа полейте статистику по папкам:
doveadm mailbox status -u user@example.com messages vsize '*'
Это быстро показывает, где «лежит» объём. После точечной чистки (или массовых перемещений) делайте пересчёт:
doveadm quota recalc -u user@example.com
MDBOX: нюансы учёта и физическая чистка
При формате хранения mdbox Dovecot хранит несколько писем в одном файле. Логическая чистка (expunge) лишь помечает сообщения удалёнными внутри контейнеров. Чтобы вернуть место на диске, периодически запускайте:
doveadm purge -u user@example.com
Подробнее о переходе на формат mdbox см. руководство по миграции на mdbox. В остальном настройка квот и предупреждений такая же, как для Maildir++.

Типичные ошибки и как их избежать
- Забыли включить плагин в IMAP: без
imap_quotaклиенты не увидят квоту. Проверьтеprotocol imap { mail_plugins = $mail_plugins quota imap_quota }. - Не эскейпят проценты: в
quota_warningпишите80%%,90%%и т.д. - Расхождения после ручной чистки: всегда делайте
doveadm quota recalcпосле массовых удалений вне IMAP-клиента. - Слишком строгая автоматическая чистка: ограничьте действия безопасными папками (Trash/Junk) и добавьте отчётность.
- Отсутствует запас: настройте
quota_graceхотя бы в 5–10%% — это снижает риск потери важной входящей почты при неожиданном пике.
Проверка и отладка
doveadm quota get -u user@example.com— текущее состояние корней квот.doveadm quota recalc -u user@example.com— пересчитать usage.tail -f /var/log/maillogилиjournalctl -u dovecot -f— видеть срабатывания предупреждений и отказов.doveadm mailbox status -u user@example.com messages vsize '*'— быстрый объём по папкам.
Чек-лист внедрения
- Включить
quotaиimap_quotaв нужных протоколах. - Определить правила: общий
storage, при необходимостиmessages, игнорируемые папки. - Добавить
quota2при необходимости второго корня (например, лимит по количеству писем). - Настроить
quota_warningна 80/90/95/100% и почтовый скрипт. - Опционально:
quota-statusдля MTA, чтобы не принимать лишнее. - Настроить деликатную чистку (Trash/Junk) и пересчёт квот по расписанию.
- Проверить на тестовом ящике: заполнение, срабатывание предупреждений, поведение LMTP/IMAP при переполнении.
Итог: грамотно настроенные квоты в Dovecot — это предсказуемое потребление диска, меньше аварийных отказов доставки и понятные пользователю сигналы о нехватке места. Используйте второй корень квот для сложных политик и не забывайте о «мягкой» автоматизации чистки.


