Ящик Dovecot переполнен, а письмо не удаляется: почему клиент упирается в квоту при попытке освободить место
Это статья для сисадмина, которому в пятницу вечером пишет бухгалтер: «почта не приходит, мне сказали ящик переполнен, я удаляю письма, а они не удаляются». И он прав — они действительно не удаляются. Покажу, что на самом деле делает почтовый клиент в момент удаления, почему при полной квоте отказывает именно первая из трёх IMAP-команд, чем освободить место прямо сейчас без правки конфига и перезапуска сервера, как правильно дать Корзине запас в Dovecot 2.3 и в новом синтаксисе 2.4, и почему самый популярный «фикс» — исключить Trash из учёта — через полгода приводит к переполненному диску. С командами, разбором реального ремонта почтового сервера транспортной компании и честным перечислением того, что в этой теме спорно.
Что на самом деле происходит в момент удаления письма
Пользователь думает, что удаление письма — это одна операция. На деле почтовый клиент по IMAP чаще всего делает три разных вещи подряд: копирует письмо в папку Trash (команда COPY), ставит на исходное письмо флаг \Deleted (STORE) и только потом физически вычищает помеченное (EXPUNGE). Логика понятная и правильная — так письмо не пропадает бесследно, оно оказывается в Корзине. Но обратите внимание на порядок: первым делом клиент пытается ЗАПИСАТЬ новые данные в ящик. А ящик уже полон.
Дальше всё предсказуемо. Dovecot честно отвечает отказом на COPY, потому что копия письма — это плюс к расходу квоты, а расход и так на пределе. По RFC 9208 (расширение QUOTA для IMAP) сервер должен вернуть на APPEND/COPY/MOVE тегированный ответ NO с кодом OVERQUOTA. Клиент видит отказ на первом же шаге, отменяет всю цепочку и рисует пользователю что-нибудь вроде «Не удалось переместить сообщение». Формулировка почти всегда невнятная — про квоту в ней может не быть ни слова, и человек искренне уверен, что «почта сломалась».
Живая сессия выглядит вот так — я снимал её telnet-ом с самого сервера, чтобы не гадать по логам клиента:
a01 COPY 4213 "Trash"
a01 NO [OVERQUOTA] Quota exceeded (mailbox for user is full)
a02 STORE 4213 +FLAGS (\Deleted)
a02 OK Store completed.
a03 EXPUNGE
* 4213 EXPUNGE
a03 OK Expunge completed.И вот здесь главное, ради чего вообще стоит читать дальше. Отказала только первая команда. Вторая и третья при полной квоте отрабатывают штатно — и так и должно быть: пометка \Deleted ничего не записывает, а EXPUNGE только освобождает место. То есть удалить письмо при переполненном ящике технически можно всегда. Ломается не удаление, ломается конкретно «перенос в Корзину».
Из этого следует практический вывод, который экономит кучу времени на первой линии: если пользователь не может ничего удалить — не надо сразу лезть в квоты и раздавать гигабайты. Достаточно один раз обойти шаг с копированием в Trash. Способов два: сделать это на сервере через doveadm или переключить клиент в режим «просто помечать удалённым». Про оба расскажу ниже.
- COPY — копия письма в Trash. Именно она падает с [OVERQUOTA], когда квота выбрана.
- STORE +FLAGS (\Deleted) — пометка исходного письма. Работает при любой заполненности.
- EXPUNGE — физическое удаление помеченных. Работает при любой заполненности, только освобождает место.
- Часть клиентов вместо COPY использует серверный MOVE (RFC 6851) — поведение при полной квоте зависит от версии и настроек, проверяйте на своём стенде, а не по чужой статье.
Первая помощь: освободить место за пять минут, не трогая конфиг
Когда ящик встал колом и почта не принимается, конфиг править поздно — там ещё перезапуск, там ещё проверка. Сначала разгребаем руками, потом чиним причину. Весь набор инструментов — это doveadm, он работает от root на самом сервере и квоту при удалении не спрашивает.
Начинаю всегда с двух команд. Первая показывает реальную картину, вторая — проверяет, не врёт ли счётчик. Пересчёт квоты нужен чаще, чем кажется: при бэкенде maildir файл maildirsize иногда расходится с содержимым ящика после ручного копирования писем, восстановления из архива или сбоя ФС. Я видел ящик, который «занимал» 20 ГБ при реальных 6 — там вообще нечего было чистить, надо было пересчитать.
# что сервер думает о расходе
doveadm quota get -u buh@fura.example
# пересчитать, если цифра выглядит подозрительно
doveadm quota recalc -u buh@fura.exampleДальше ищем, где именно лежат гигабайты. Пользователи почти никогда не угадывают: они уверены, что «много входящих», а на деле раздуты «Отправленные» с приложениями или та самая Корзина, которую не чистили три года. Смотрю размеры папок и сразу прикидываю, что можно снести без обсуждений:
# размеры всех папок ящика (vsize — виртуальный размер, тот, что считает квота)
# ключ -t НЕ ставить: он суммирует все папки в одну цифру
doveadm mailbox status -u buh@fura.example vsize '*'
# сколько писем попадёт под чистку — СНАЧАЛА посчитать, потом удалять
doveadm search -u buh@fura.example mailbox 'Sent' larger 10M savedbefore 365d | wc -lИ только потом — удаление. doveadm expunge принимает тот же язык поисковых запросов, что и doveadm search, поэтому правило простое: сначала прогоняете условие через search и смотрите на число, потом тем же условием запускаете expunge. Никаких «ну примерно так»:
# крупные отправленные старше года
doveadm expunge -u buh@fura.example mailbox 'Sent' larger 10M savedbefore 365d
# полностью вычистить Корзину
doveadm expunge -u buh@fura.example mailbox 'Trash' all
# после чистки — обязательно пересчёт и проверка
doveadm quota recalc -u buh@fura.example && doveadm quota get -u buh@fura.example- doveadm quota get -u — текущий расход, лимит и процент.
- doveadm quota recalc -u — пересчёт, когда счётчик разошёлся с реальностью.
- doveadm mailbox status -u ... vsize '*' — размеры папок по отдельности (с -t выйдет одна общая сумма).
- doveadm search ... | wc -l — репетиция перед expunge с тем же условием.
- doveadm expunge -u ... mailbox 'Trash' all — самая частая и самая безопасная разовая мера.
Разбор: транспортная компания на 26 рабочих мест
Стенд: почтовый сервер условной транспортной компании «Фура-Сервис» — Ubuntu 22.04, Dovecot 2.3.16 из штатного репозитория, бэкенд квоты count, виртуальные ящики на отдельном томе, 34 ящика, из них живых 26 (остальное — общие адреса диспетчерской, отдела логистики и уволенных водителей-экспедиторов). Квота на всех одинаковая: quota_rule = *:storage=15G. Клиенты — Outlook по IMAP у большинства и Thunderbird у пары диспетчеров. Обращение классическое: «у главбуха не приходит почта и она не может ничего удалить, срочно».
Смотрю. doveadm quota get -u buh@fura.example показывает 15,0 ГБ из 15 ГБ, 100 %. Пересчёт ничего не меняет — счётчик не врал. Раскладка по папкам оказалась поучительной: INBOX 3,8 ГБ, «Отправленные» 4,4 ГБ, архивные подпапки по годам суммарно 0,7 ГБ, и Trash — 6,1 ГБ. Шесть гигабайт в Корзине. То есть человек три года исправно «удалял» почту, и все эти три года она никуда не девалась, а спокойно лежала в Trash и съедала его же квоту. Классика, встречаю такое примерно у каждого второго клиента, где Корзина не чистится автоматически.
Разгребал в три захода. Сначала вычистил Корзину целиком — doveadm expunge -u buh@fura.example mailbox 'Trash' all, порядка 6,1 ГБ, отработало за 40 секунд с небольшим. Потом снёс отправленные с вложениями старше двух лет: search показал 812 писем, expunge освободил ещё 2,9 ГБ. Итого расход упал с 15,0 до 6,0 ГБ, 40 % от лимита. Почта пошла в течение минуты — очередь Postfix, которая копилась с ночи, разошлась сама. Отдельно проверил, что в очереди не накопилось отбойников: политика quota-status на тот момент подключена не была, и письма честно ждали в deferred, а не отбивались отправителям — повезло, ничего не потерялось.
Дальше — причина, а не следствие. Корзине дал запас в 1 ГБ поверх общего лимита и включил автоочистку через 30 дней, Junk — через 14. Прикрутил предупреждения на 80 % и 95 %, чтобы человек узнавал о проблеме заранее, а не в момент остановки почты. И подключил quota-status как policy-сервис к Postfix, чтобы переполненный ящик отбивался прямо на SMTP, а не наполнял очередь. Через полгода тот же ящик держится в районе 7–8 ГБ и обращений по нему не было. Единственное, что не прижилось — переключение Outlook в режим «помечать как удалённое»; про это отдельно ниже, решение спорное и я на нём не настаиваю.
- Было: 15,0 / 15 ГБ, приём почты остановлен, пользователь не может удалить ни одного письма.
- Найдено: Trash 6,1 ГБ (не чистилась ~3 года), «Отправленные» 4,4 ГБ.
- Сделано сразу: expunge Корзины + отправленные с вложениями старше 2 лет — освобождено 9,0 ГБ.
- Сделано потом: запас 1 ГБ на Trash, autoexpunge 30 дней, предупреждения 80/95 %, quota-status в Postfix.
- Стало: 6,0 ГБ (40 %), через полгода 7–8 ГБ, повторных обращений нет.
Серверный фикс: дать Корзине запас — и понимать, что это на самом деле значит
Правильное лечение — не «убрать Корзину из учёта», а «разрешить сохранение в Корзину чуть выше общего потолка». Разница принципиальная, к ней вернусь через абзац. В Dovecot 2.3 это делается парой правил в блоке plugin. Обратите внимание на двойной процент: в конфиге Dovecot символ % — начало подстановки переменной, поэтому проценты экранируются как %%. На этом спотыкаются регулярно и потом ищут, почему сервис не стартует.
plugin {
quota = count:User quota
quota_vsizes = yes
quota_rule = *:storage=15G
quota_rule2 = Trash:storage=+1G
quota_rule3 = Spam:ignore
quota_grace = 10%%
}В ветке 2.4 конфигурация квот переписана: вместо нумерованных quota_rule появились именованный фильтр квота-рута и отдельные настройки для каждой папки прямо внутри namespace. Актуальный релиз на сентябрь 2026 — 2.4.5 от 28 августа 2026 года. Если планируете переезд с 2.3 — учитывайте, что это не косметика, а другой формат, конфиг переписывается руками:
quota "User quota" {
quota_storage_size = 15G
quota_message_count = 100000
}
namespace inbox {
mailbox Trash {
quota_storage_extra = 1G
mailbox_autoexpunge = 30d
}
mailbox Spam {
quota_ignore = yes
}
}А теперь честно про то, что этот параметр делает — потому что в половине руководств написано неверно, включая довольно популярные. Формулировка «у Корзины появляется своя квота в 1 ГБ» — неправильная. И quota_rule2 = Trash:storage=+1G в 2.3, и quota_storage_extra = 1G в 2.4 означают одно и то же: при сохранении письма именно в эту папку общий допустимый расход по квота-руту считается на гигабайт больше. Отдельного счётчика на Корзину не появляется, содержимое Trash по-прежнему входит в общий расход ящика. Практический смысл ровно один — пользователь, упёршийся в потолок, сможет утащить в Корзину ещё до гигабайта и тем самым разблокировать себе удаление. Это буфер, а не отдельный лимит.
Отсюда вытекает обязательный второй компонент: автоочистка. Буфер без автоочистки — это отложенная на месяц та же самая проблема, потому что письма из Корзины никуда не денутся сами. В 2.3 параметр называется autoexpunge и задаётся в описании папки, в 2.4 он переименован в mailbox_autoexpunge. Ставлю 30 дней на Trash и 14 на Junk — за восемь лет ни одной претензии по этим срокам не было, а вот «я удалил и через месяц понадобилось» случается, поэтому меньше 30 дней на Корзину я не ставлю принципиально.
# Dovecot 2.3
namespace inbox {
mailbox Trash {
auto = subscribe
special_use = \Trash
autoexpunge = 30d
}
mailbox Junk {
auto = subscribe
special_use = \Junk
autoexpunge = 14d
}
}Есть и третий инструмент, про который вспоминают реже, — плагин trash. Он работает поверх квоты и меняет саму реакцию на переполнение: вместо ответа OVERQUOTA сервер удаляет самые старые письма из перечисленных папок в порядке приоритета, пока новое сообщение не поместится. В 2.3 плагин подключается через mail_plugins = $mail_plugins quota trash и отдельный файл с приоритетами, в 2.4 приоритет задаётся прямо в описании папки параметром trash_priority — чем меньше число, тем раньше папку начнут чистить:
# Dovecot 2.3: /etc/dovecot/conf.d/90-quota.conf
plugin {
trash = /etc/dovecot/dovecot-trash.conf.ext
}
# /etc/dovecot/dovecot-trash.conf.ext
1 Spam
2 Trash
# Dovecot 2.4
namespace inbox {
mailbox Spam {
trash_priority = 1
}
mailbox Trash {
trash_priority = 2
}
}Важная оговорка из документации: плагин никогда не удаляет письма из той папки, в которую идёт сохранение. Если в списке только Trash, то перенос в Корзину он не спасёт — удалять ему будет не из чего. Работает связка, когда перед Корзиной стоит Spam: копирование в Trash выталкивает старый спам, а входящая почта и сохранение в «Отправленные» выталкивают и спам, и Корзину. Для FS-квоты плагин не работает, нужен count или maildir.
Сам я включаю trash-плагин осторожно. Он молча удаляет письма без какого-либо уведомления, и если бухгалтер держит в Корзине «на всякий случай» то, что потом ищет, объяснять придётся вам. Поэтому у клиентов с живыми людьми в ящиках я ставлю его только на Spam/Junk, а Корзину чищу предсказуемо — через autoexpunge по сроку, о котором пользователи знают. Для служебных ящиков, куда сыплются уведомления из 1С, трекинга и телематики, trash с приоритетом на Trash — нормальное решение.
- 2.3: `quota_rule2 = Trash:storage=+1G` — плюс гигабайт к общему потолку при записи в Trash.
- 2.4: `quota_storage_extra = 1G` внутри `mailbox Trash { }` — то же самое в новом синтаксисе.
- Ни то, ни другое не создаёт отдельную квоту Корзины: её содержимое по-прежнему считается в общем расходе.
- Без autoexpunge / mailbox_autoexpunge буфер лишь откладывает проблему.
- Размер запаса берите от типичного письма, а не от квоты: 500 МБ — 1 ГБ хватает почти всегда.
- Плагин trash (`trash_priority` в 2.4, файл приоритетов в 2.3) удаляет старые письма вместо отказа, но не из папки назначения — Spam ставьте раньше Trash.
Три способа сделать хуже, которые я вижу из раза в раз
Первый и самый вредный — quota_ignore = yes на Trash (в 2.3 — quota_rule2 = Trash:ignore). Логика на первый взгляд безупречная: раз Корзина мешает удалять, давайте не будем её считать. Проблема в том, что после этого удаление письма перестаёт освобождать место в принципе — оно просто перекладывается в неучитываемую папку. Пользователь чистит ящик, цифра расхода падает, все довольны, а на диске не освобождается ни байта. Дальше растёт Корзина, растёт раздел, и в какой-то момент вы разбираете переполнение тома у сервера целиком, где половина объёма — «удалённая» почта. Учёт квоты после этого врёт всем: и мониторингу, и вам.
Второй — надежда на quota_grace (в 2.4 — quota_storage_grace). Про него регулярно думают, что это «мягкий лимит, который позволит немножко превысить и разобраться». Не позволит. Во-первых, послабление относится к доставке через LDA/LMTP, то есть к входящей почте, а не к тому, что делает IMAP-клиент. Во-вторых — и это ключевое — grace даёт превысить лимит один раз; когда квота уже за пределом, послабление больше не действует. К моменту, когда пользователь звонит вам, grace давно израсходован и в разборе не участвует. По умолчанию в 2.3 он равен 10 % от лимита, в 2.4 — фиксированные 10M (формат значения тоже поменялся), и трогать его ради этой задачи бессмысленно.
Третий — «поднимем квоту на пару дней, человек почистит». Не почистит. Через два дня расход снова упрётся в новый потолок, потому что удалять он по-прежнему будет в Корзину, а Корзина по-прежнему в общем зачёте. Плюс про временную надбавку забывают, она разъезжается по половине ящиков, и через год у вас нет ни одной внятной политики хранения. Если объём действительно нужен — увеличивайте осознанно и всем, а не точечно и «на время».
Отдельная категория — «выключим квоты вообще, у нас же большой диск». Работает ровно до первого сотрудника, который начнёт пересылать по почте сканы ТТН и путевых листов пачками по 50 страниц, и до первой рассылки со вложением на 40 МБ по всей компании. Квота — это не про экономию гигабайтов, это про то, чтобы один ящик не уронил приём почты всей организации. Мне это стоило одного ночного разбора, чтобы усвоить.
- quota_ignore на Trash — удаление перестаёт освобождать место, диск растёт незаметно.
- Ставка на quota_grace — не про IMAP, действует один раз и уже не работает, когда лимит превышен.
- Временное повышение квоты — возвращается через два дня и остаётся навсегда.
- Полное отключение квот — переносит проблему с одного ящика на весь сервер.
Настройка на стороне клиента: кому и когда это стоит менять
Раз ломается именно копирование в Корзину, его можно просто отключить — тогда клиент будет ставить \Deleted и делать EXPUNGE, а обе эти команды при полной квоте работают. В Thunderbird переключатель живёт в «Параметрах сервера» для конкретной учётной записи: «При удалении сообщения» — варианты «Переместить его в папку», «Пометить его как удалённое» и «Удалить его немедленно». Нужен средний. В Apple Mail снимается галочка переноса удалённых в «Корзину» в настройках учётной записи. В веб-клиентах (Roundcube, SOGo) обычно есть либо настройка «пропускать Корзину», либо штатное сочетание Shift+Delete для удаления мимо неё.
С Outlook сложнее. В классическом Outlook для IMAP-учётки переключатель ещё есть: «Параметры учётной записи» → «Другие настройки» → вкладка «Удалённые», вариант «Помечать элементы для удаления, но не перемещать их автоматически» — но спрятан он так, что пользователь сам его не найдёт, а после пересоздания профиля настройка теряется. В новом Outlook для Windows и в веб-клиентах Microsoft такой опции нет. Поэтому в парке, где Outlook — стандарт (а это большинство наших клиентов), клиентский путь работает плохо, и основным остаётся серверный: запас на Trash плюс автоочистка.
Теперь честно про спорность. Режим «помечать как удалённое» решает проблему квоты, но ломает привычку: письмо исчезает из списка (или отображается зачёркнутым — зависит от клиента), и «достать из Корзины» становится нельзя. Для сисадмина это удобно, для бухгалтера — стресс и заявка в поддержку. Я применяю такой режим точечно: техническим ящикам, ящикам-приёмникам автоматических уведомлений, служебным учёткам. Живым людям — не трогаю, им настраиваю сервер. Массово переключать всю компанию я не советую, эффект от такого решения обычно отрицательный.
- Thunderbird: Параметры сервера → При удалении сообщения → «Пометить его как удалённое».
- Apple Mail: снять перенос удалённых писем в «Корзину» в настройках учётной записи.
- Roundcube / SOGo: Shift+Delete или настройка «не использовать Корзину».
- Outlook: в классическом — «Другие настройки» → «Удалённые» → «Помечать для удаления»; в новом Outlook опции нет, лечится на сервере.
- Разумная область применения: служебные и технические ящики, не рядовые пользователи.
Чтобы не повторялось: предупреждения, отбой на SMTP и мониторинг
Разовая чистка — это не решение, это откладывание. Нормальная схема состоит из трёх частей: пользователь узнаёт о приближении к лимиту заранее, отправитель узнаёт о переполнении сразу, а вы видите проблемные ящики до звонка. В Dovecot 2.3 первое делается через quota_warning: сервер сам дёргает скрипт при пересечении порога, а скрипт отправляет письмо владельцу ящика. Пороги я ставлю на 80 % и 95 % — одного мало, человек пропустит. Если скачок расхода перепрыгнул оба порога сразу, Dovecot выполнит только старший — это штатно.
# Dovecot 2.3
plugin {
quota_warning = storage=95%% quota-warning 95 %u
quota_warning2 = storage=80%% quota-warning 80 %u
}
service quota-warning {
executable = script /usr/local/bin/quota-warning.sh
user = dovecot
unix_listener quota-warning {
user = vmail
}
}В 2.4 то же самое пишется блоками внутри квота-рута, а однобуквенные переменные вроде %u заменены на %{user}:
# Dovecot 2.4
quota "User quota" {
quota_storage_size = 15G
quota_warning warn-95 {
quota_storage_percentage = 95
execute quota-warning {
args = 95 %{user}
}
}
quota_warning warn-80 {
quota_storage_percentage = 80
execute quota-warning {
args = 80 %{user}
}
}
}Второе — политика quota-status для Postfix. Без неё письмо в переполненный ящик просто ложится в очередь и болтается там до истечения срока (по умолчанию несколько суток), после чего отбивается отправителю с большим опозданием. С политикой Postfix спрашивает у Dovecot состояние получателя ещё на этапе RCPT TO и отбивает переполненный ящик сразу: в 2.3 ответ задаёт quota_status_overquota (в документации — 552 5.2.2 Mailbox is full), в 2.4 значение по умолчанию — 554 5.2.2. Код 552 постоянный: Postfix вернёт отправителю отказ, а не отложит письмо. Отправитель узнаёт о проблеме за секунду, а не через двое суток — и, что важнее, сам звонит вашему пользователю. Это лучший из известных мне способов заставить человека почистить почту вовремя.
# dovecot 2.3: сервис политики
plugin {
quota_status_success = DUNNO
quota_status_nouser = DUNNO
quota_status_overquota = "552 5.2.2 Mailbox is full"
}
service quota-status {
executable = quota-status -p postfix
unix_listener /var/spool/postfix/private/quota-status {
user = postfix
}
client_limit = 1
}
# postfix main.cf
smtpd_recipient_restrictions =
permit_mynetworks,
reject_unauth_destination,
check_policy_service unix:private/quota-statusТретье — мониторинг. Мне достаточно ежедневного отчёта по ящикам, перешагнувшим 85 %: за неделю их видно, за месяц — видно тенденцию, и вы приходите к человеку до того, как у него встанет почта. Ключ -A в командах чтения безопасен и здесь как раз уместен. Порядок и состав колонок в выводе на разных сборках отличался, поэтому проверьте его на своей, прежде чем зашивать номера полей в скрипт:
# ящики, у которых расход по STORAGE перевалил за 85 %
doveadm -f tab quota get -A | awk -F'\t' 'NR>1 && $3=="STORAGE" && $6+0 >= 85 {print $1, $6"%"}'И последнее, про приоритеты. Если у вас сейчас горит и времени мало — делайте по порядку: вычистили Корзину через doveadm, дали Trash запас в 1 ГБ, включили autoexpunge на 30 дней. Три действия, полчаса работы, снимают процентов девяносто обращений по этой теме. Предупреждения, policy-сервис и мониторинг — важные, но их спокойно можно доделать на следующей неделе. А вот на что действительно можно забить — на попытки переучить пользователей «правильно удалять почту». Не переучите. Настраивайте сервер.
- quota_warning на 80 % и 95 % (в 2.4 — именованные блоки `quota_warning warn-95 { quota_storage_percentage = 95; execute quota-warning { ... } }`).
- check_policy_service на quota-status в Postfix — отбой 5.2.2 прямо на RCPT TO (552 в примере 2.3, 554 по умолчанию в 2.4).
- autoexpunge / mailbox_autoexpunge: Trash 30 дней, Junk 14 дней.
- Ежедневный отчёт по ящикам выше 85 % — в Zabbix или просто письмом админу.
- Порядок при пожаре: expunge Корзины → запас на Trash → автоочистка. Остальное потом.
Частые вопросы
Почему письмо не удаляется, если я как раз пытаюсь освободить место?
Потому что почтовый клиент удаляет письмо в три шага: сначала копирует его в папку Trash (COPY), затем ставит флаг \Deleted и только потом делает EXPUNGE. Первый шаг — это запись новых данных, и при выбранной квоте Dovecot отвечает на него NO [OVERQUOTA]. Клиент отменяет всю цепочку. При этом сами по себе пометка \Deleted и EXPUNGE при полной квоте работают всегда — ломается именно перенос в Корзину, а не удаление.
Можно ли просто исключить Корзину из подсчёта квоты?
Технически можно (`quota_ignore = yes` в 2.4, `Trash:ignore` в 2.3), но делать так не стоит. После этого удаление письма перестаёт освобождать место: письмо переезжает в неучитываемую папку, счётчик квоты падает, а на диске не освобождается ничего. Через несколько месяцев вы разбираете переполнение раздела, где значительная часть объёма — «удалённая» почта. Правильнее дать Корзине небольшой запас (quota_storage_extra) и включить автоочистку.
Помогает ли quota_grace разблокировать удаление?
Нет. quota_grace (в 2.4 — quota_storage_grace) относится к доставке через LDA/LMTP, то есть к входящей почте, и позволяет превысить лимит один раз (по умолчанию 10 % лимита в 2.3 и 10M в 2.4). Когда квота уже за пределом — а именно в этот момент пользователь и обращается — послабление больше не действует. К задаче «дать человеку удалить письма» этот параметр отношения не имеет.
Что делать прямо сейчас, если ящик забит и почта не приходит?
Зайти на сервер и работать через doveadm — он квоту при удалении не спрашивает. Порядок: `doveadm quota get -u user@domain` (посмотреть расход), `doveadm quota recalc -u user@domain` (убедиться, что счётчик не врёт), `doveadm mailbox status -u user@domain vsize '*'` (найти толстые папки), затем `doveadm expunge -u user@domain mailbox 'Trash' all`. Условие для expunge сначала прогоняйте через doveadm search — и никогда не используйте ключ -A в удаляющих командах.
Правда ли, что quota_storage_extra создаёт отдельную квоту для Корзины?
Нет, и это самое частое заблуждение по теме. И `quota_rule2 = Trash:storage=+1G` в 2.3, и `quota_storage_extra = 1G` в 2.4 означают, что при сохранении письма именно в эту папку общий допустимый расход считается на гигабайт больше. Отдельного счётчика не появляется, содержимое Корзины по-прежнему входит в общий расход ящика. Это буфер, позволяющий разблокировать удаление, поэтому его обязательно дополняют автоочисткой.
Чем настройка квот в Dovecot 2.4 отличается от 2.3?
Формат переписан. Вместо нумерованных `quota_rule`/`quota_rule2` в блоке plugin в 2.4 используется именованный фильтр квота-рута — `quota "User quota" { quota_storage_size = 15G }` — и настройки на уровне отдельных папок внутри namespace (quota_storage_extra, quota_ignore). Параметр autoexpunge переименован в mailbox_autoexpunge, quota_grace — в quota_storage_grace (и по умолчанию теперь 10M вместо 10 %), приоритеты trash-плагина переехали из отдельного файла в `trash_priority`, а quota_warning стал именованным блоком. Это не косметическая правка: при переезде с 2.3 конфиг квот переписывается вручную. Актуальный релиз ветки на сентябрь 2026 — 2.4.5.
Поможет ли плагин trash, если Корзина уже забита?
Частично. Плагин trash вместо отказа по квоте удаляет самые старые письма из папок по приоритету (`trash_priority` в 2.4, файл приоритетов в 2.3), но никогда не трогает папку, в которую идёт сохранение. Если в списке только Trash, перенос в Корзину он не спасёт. Рабочая схема — Spam с приоритетом 1, Trash с приоритетом 2: тогда копирование в Корзину выталкивает старый спам. Учтите, что удаление происходит молча, поэтому для ящиков живых сотрудников я предпочитаю autoexpunge по сроку.
Источники
- Dovecot 2.4 — Quota plugin — Официальная документация Dovecot 2.4.0, раздел Core → Plugins → quota: настройки quota_storage_size, quota_storage_extra, quota_storage_grace (по умолчанию 10M, только для LDA/LMTP), quota_ignore, quota_warning, quota_status_overquota (по умолчанию 554 5.2.2), пример `mailbox Trash { quota_storage_extra = 100M }` и синтаксис квота-рута `quota "User quota" { }`. https://doc.dovecot.org/2.4.0/core/plugins/quota.html
- Dovecot 2.3 — Quota Plugin и Quota Configuration — Configuration Manual ветки 2.3: описание проблемы move-to-trash («the first COPY command will fail» при превышении квоты), quota_vsizes для драйвера count; правила `quota_rule = *:storage=1G`, `quota_rule2 = Trash:storage=+100M`, `quota_rule3 = SPAM:ignore`, quota_grace (по умолчанию 10 % лимита), quota_warning. https://doc.dovecot.org/2.3/configuration_manual/quota_plugin/ и https://doc.dovecot.org/2.3/configuration_manual/quota/
- RFC 9208 — IMAP QUOTA Extension — IETF, март 2022. Определяет ресурсные лимиты в IMAP, команды GETQUOTA/GETQUOTAROOT/SETQUOTA и код ответа OVERQUOTA: сервер SHOULD вернуть его в тегированном NO на APPEND/COPY/MOVE, если операция выводит ящик за лимит. https://www.rfc-editor.org/rfc/rfc9208.html
- Dovecot Core — релизы — Страница релизов dovecot/core на GitHub: актуальная ветка 2.4, последний релиз на момент написания — 2.4.5 от 28 августа 2026 года. https://github.com/dovecot/core/releases
- Dovecot — Trash plugin (2.3 и 2.4) — Удаление самых старых писем из папок по приоритету вместо ошибки квоты; требует quota с не-FS драйвером; не удаляет из папки, в которую идёт сохранение. 2.3: `plugin { trash = /etc/dovecot/dovecot-trash.conf.ext }`; 2.4: `trash_priority`. https://doc.dovecot.org/2.3/configuration_manual/plugins/trash_plugin/ и https://doc.dovecot.org/2.4.0/core/plugins/trash.html
- Dovecot — Upgrading from 2.3 to 2.4 — Официальное руководство по переходу: разделение quota/quota_rule на отдельные настройки, quota_grace → quota_storage_grace, quota_over_flag → quota_over_status_current, отказ от однобуквенных переменных (%u → %{user}), обязательные dovecot_config_version/dovecot_storage_version. https://doc.dovecot.org/main/installation/upgrade/2.3-to-2.4.html
