Имеется очень большое количество пользователей (>1000), большая часть из которых не сортируют свою почту, устраивая свалку в папке “Входящие”. Поскольку объём ящиков ограничен (для ограничения размера свалки), случаются переполнения почтовых ящиков и важная корреспонденция уже не доходит до получателей вовремя.
Скрипт очистки
Чтобы не ходить вокруг да около сразу приведу конечный текст получившегося скрипта. Запускать скрипт нужно от пользователя zimbra.
#!/bin/bash # as_clean_mbox v1.0 # (c) 2016 AS, https://as.zabedu.ru result="/tmp/result" domain="zabedu.ru" delete_proc_limit=98 delete_mess_count=200 admin="admin@$domain" rm -f $result touch $result server=`/opt/zimbra/bin/zmhostname` /opt/zimbra/bin/zmprov gqu $server | grep $domain | awk {'print $1" "$3" "$2'} | sort | while read line do user=`echo $line | cut -f1 -d " "` usage=`echo $line | cut -f2 -d " "` quota=`echo $line | cut -f3 -d " "` if [ "$quota" -ne 0 ] then proc=$((100 * $usage / $quota)) if [ "$proc" -ge "$delete_proc_limit" ] then notclear=`/opt/zimbra/bin/zmprov ga $user | grep -e 12345678-bbdd-abcd-dcba-12345aabbcc -e 87654321-aacc-dcaf-ddff-54321eeffdd | wc -l` if [ "$notclear" -eq 0 ] then mess_count=0 mess=`/opt/zimbra/bin/zmmailbox -z -m $user s -t message -l $delete_mess_count -s dateAsc "in:inbox" | head -n -1 | tail -n +5 | sed -e "s/^\s\s*//" | sed -e "s/\s\s*/ /" | cut -d" " -f2 | tr "\n" "," | sed 's/.$//'` if [ ${#mess} -ge $delete_mess_count ] then /opt/zimbra/bin/zmmailbox -z -m $user deleteMessage `echo $mess` mess_count=$((mess_count + 1 + `echo $mess | grep -o ',' | wc -l`)) fi /opt/zimbra/bin/zmmailbox -z -m $user emptyFolder /Trash echo "$user $mess_count" >> $result fi fi fi done if [ `wc -l < $result` -ne 0 ] then (echo "Subject:Clean mailbox"; cat $result;) | /usr/sbin/sendmail -F mail@$domain $admin fi
Разбор по кускам
Основной функционал начинается с вызова:
zmprov gqu `zmhostname`
Данная команда возвращает список пользователей с указанием использованного дискового пространства и размера установленной квоты. Поскольку на сервере может быть несколько доменов, добавлен фильтр:
grep $domain
Далее берем только тех пользователей, у которых есть квота:
if [ "$quota" -ne 0 ]
Все служебные пользователи не имеют квоты ($quota=0), а это вызовет ошибку на следующем шаге, т.к. делить на ноль нельзя. Вычисляем процент использования квоты:
proc=$((100 * $usage / $quota))
Деление в bash целочисленное, всё дробное просто отбрасывается, если нужны дробные значения, то посмотрите bc. Далее берём только тех пользователей у которых процент использования выше заданного значения delete_proc_limit (в моём случае 98):
if [ "$proc" -ge "$delete_proc_limit" ]
Здесь "больше или равно" (-ge) взято как раз из-за целочисленного деления.
Следующий вопрос: а у всех ли категорий (читай: классов обслуживания) пользователей можно вот так взять и почистить почту? Если "нет", то таких пользователей нужно исключить из списка очистки! Для этого можно проверить класс обслуживания пользователя (COS):
notclear=`zmprov ga $user | grep -e 12345678-bbdd-abcd-dcba-12345aabbcc -e 87654321-aacc-dcaf-ddff-54321eeffdd | wc -l` if [ "$notclear" -eq 0 ]
Если пользователь принадлежит одному из заданных COS, то он выкидывается из списка. Список всех COS и их Id можно получить так:
zmprov gac -v | grep -e cn: -e zimbraId:
Обратите внимание, что у пользователей из COS = "default" id класса (zimbraCOSId) в атрибутах не пишется, т.е. если у пользователя отсутствует zimbraCOSId, значит от относится к классу обслуживания default.
Теперь нужно получить id сообщений:
mess=`zmmailbox -z -m $user s -t message -l $delete_mess_count -s dateAsc "in:inbox" | head -n -1 | tail -n +5 | sed -e "s/^\s\s*//" | sed -e "s/\s\s*/ /" | cut -d" " -f2 | tr "\n" "," | sed 's/.$//'`
Данная команда возвратит список id сообщений указанного пользователя. Количество сообщений ограничено переменной delete_mess_count, максимальное значение 1000. Фильтр сообщений задается строкой "in:inbox", можно составить любой поисковый запрос в веб-интерфейсе zimbra и использовать его здесь. "-s dateAsc" задает сортировку сообщений, в нашем случае сортировка по дате, начиная с последних сообщений. Для сортировки сообщений доступны следующие параметры: dateDesc, dateAsc, subjDesc, subjAsc, nameDesc, nameAsc, none, rcptAsc, rcptDesc.
Если сообщения найдены,
if [ ${#mess} -ge $delete_mess_count ]
то приступаем к их удалению:
zmmailbox -z -m $user deleteMessage `echo $mess`
Все выбранные сообщения удаляются одной командой, можно удалять и по одному в цикле, но это сильно нагрузит процессор.
Последний штрих - принудительная очистка корзины:
zmmailbox -z -m $user emptyFolder /Trash
Теперь имя пользователя и количество удаленных сообщений записываем в файл:
echo "$user $mess_count" >> $result
И если в итоге файл получился не пустой, то отправляем его админу ($admin) в качестве отчета:
(echo "Subject:Clean mailbox"; cat $result;) | sendmail -F mail@$domain $admin
После тестирования работы скрипта и подгонки значений констант под свой сервер, можно прописать его запуск в cron. У себя я поставил ежедневный ночной запуск. Готово, теперь не будет постоянных переполнений ящиков и скопившейся на сервере очереди сообщений.
Внимание! При работе данного скрипта возможна ситуация, когда сообщения у пользователя структурированы по папкам (не хранятся в папке Входящие) и тут место заканчивается. В данной ситуации скрипт может, удалив 200 писем из Входящие, удалить все последние и еще не отработанные письма! Поэтому, без согласования с вышестоящим начальством и без предупреждения пользователей чистку лучше не начинать.
Предупреждение о скором переполнении ящика система делает сама, достаточно внести в него соответствующее дополнение об очистке, редактируется тут:
Настройка -> Класс Обслуживания -> {выбираем класс} -> Дополнительно -> Шаблон предупреждений о достижении лимита.
Все почистить иногда проще, чем заставить пользователей держать свою почту в порядке.
А как бы на основании этого скрипта сделать так, что бы он работал только с одном ящиком, причем с безлимитным ограничением по общему и удалял только те письма, которые старше двух недель?
THEDATE=$(date -d ‘-395 days’ +%m/%d/%y)
‘-395 days’ замени на ‘-14 day’ и будет тебе счастье
опечатался
*с безлимитным ограничением по объему
Нужно изменить запрос, возвращающий id сообщений, подсказка в статье:
“Фильтр сообщений задается строкой «in:inbox», можно составить любой поисковый запрос в веб-интерфейсе zimbra и использовать его здесь.”
Попробуйте что-то следующего вида: “in:/inbox (before:$THEDATE)”, где $THEDATE – это дата ‘mm/dd/yyyy’.
мне кажется уже давно пора почтовикам сделать так чтоб с переодичностью раз в несколько лет почта чистиласьавтоматически
Согласен, функция будет полезная, но иногда бывают требования хранить всю переписку очень долго.