OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

Квоты почты в Dovecot: quota2, предупреждения и чистка при переполнении

Разбираем включение и проверку квот в Dovecot на практических примерах: лимиты storage/messages, второй корень quota2, пороги и уведомления quota_warning 80–100%, интеграция quota-status с Postfix, мягкая чистка Trash/Junk.
Квоты почты в Dovecot: quota2, предупреждения и чистка при переполнении

Квоты в почтовом сервере — базовый инструмент управления диском и стабилизации сервиса. В 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 и оповещения.

Схема интеграции Postfix с Dovecot quota-status

Предупреждения пользователям: 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. Это снизит нагрузку на очередь и ускорит отказ в случае переполнения.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Чистка при переполнении: стратегия «мягкая автоматизация»

Автоматическая чистка — тонкий момент: агрессивное удаление может привести к потере важных писем. Рекомендуется комбинировать щадящие правила и видимый пользователю отчёт.

Безопасный минимум

  • Удалять письма в 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++.

Иллюстрация очистки mdbox через doveadm purge

Типичные ошибки и как их избежать

  • Забыли включить плагин в 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 — это предсказуемое потребление диска, меньше аварийных отказов доставки и понятные пользователю сигналы о нехватке места. Используйте второй корень квот для сложных политик и не забывайте о «мягкой» автоматизации чистки.

Поделиться статьей

Вам будет интересно

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости OpenAI Статья написана AI (GPT 5)

DMARC: rua, p=quarantine и p=reject — как включить без потери доставляемости

Пошаговое руководство для админов: что такое DMARC и агрегированные отчёты rua, как правильно оформить rua=mailto, собрать XML-отч ...
Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover OpenAI Статья написана AI (GPT 5)

Floating IP для Nginx: keepalived VRRP, healthcheck и быстрый failover

Пошагово строим отказоустойчивый фронтенд на двух серверах Nginx с общим floating IP. Настраиваем keepalived (VRRP), HTTP health c ...
SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово OpenAI Статья написана AI (GPT 5)

SYNPROXY в nftables: защита VDS от TCP SYN flood пошагово

SYN flood забивает TCP-очереди и conntrack на VDS, съедая CPU. SYNPROXY в nftables отсекает мусор до TCP-стека. Разбираем принцип, ...