В нашей компании используется MS Exchange Server, в нём создано ~2000 групп рассылок: ~1700 обычных и ~300 динамических, и все это хозяйство держит под собой 2800 e-mail адресов.
Хозяев групп нет, а если и есть, то давно уволились, какого-то реестра тоже нет.
В результате, для одного департамента есть такие группы:
- DISTRIB-Отдел;
- Distrib_отдел;
- Отделъ-Пермь;
- DISTRIB_IT_Otdel.
И столько же динамических:
- Рассылка-Отдел (Москва);
- Рассылка-Отдел (Общая);
- Рассылка Пермский ф-л (Отдел);
- DST-PRM_NOT_OTDEL.
Мы с коллегами решили, что пришла пора весенней уборки.
Но как узнать какие из этих групп используются? Отключать по одной и смотреть откуда поднимется вой?
Я решил, что это не наш метод и приступил к анализу Exchange MTL (Message Tracking Logs).
Есть событие EXPAND, которое “развёртывает” группу в список получателей. “Ага”, – сказал я и начал тестировать стандартную и динамическую группы рассылки.
Первый же подвох ждал меня с динамической группой рассылки – она не порождала события EXPAND.
Второй подвох был с модерируемой динамической группой рассылки – группой рассылки, которая требует предварительного одобрения контента. Там я даже события SEND на адрес группы уже не увидел – SEND был сразу на список членов группы. Проанализировав журналы, я решил, что более перспективное событие – это SUBMIT, которое создается при попытке отправить на любой адрес. Да, в SUBMIT попадут также и отдельные ящики, но с этим уже можно работать.
Жалкие попытки изучения Python подсказали мне, что для решения задачи “встречаемых” адресов групп в логе лучше использовать структуру вида словарь/dictionary, а не стандартный массив/array, в силу возможности индексировать структуру по уникальному ключу, которым может выступить адрес группы. В итоге, вместо поиска по массиву сопоставления вы “просто” сразу переходите по индексу.
Оказывается, в Powershell тоже есть свои словари – Hashtable. Ну а дальше дело само начало спориться. 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#собираем в список все электронные адреса у стандартных групп рассылки, даже если их несколько $addresslist=(Get-DistributionGroup -ResultSize unlimited).emailaddresses.smtpaddress #добавляем туда все электронные адреса у динамических групп рассылки $addresslist+=(Get-dynamicDistributionGroup -ResultSize unlimited).emailaddresses.smtpaddress #Создаем словарь со следующей структурой: в каждой строке электронный адрес группы и количество писем, #пришедших на адрес. Инициализируем словарь нулями $dict=@{} $addresslist | %{$dict[$_] = 0} #Создаем список Mailbox-серверов для последующего опроса MessageTrackingLog, #формируя строку для удаленного подключения WinRM $Mailboxservers = Get-MailBoxServer | % { "<a href="http://$($_.Name)/PowerShell/">http://$($_.Name)/PowerShell/</a>" } #Выполняем в параллели опрос всех серверов. Время работы – примерно 30 минут на месяц логов, содержащих 160 тысяч #событий SUBMIT. Событие Submit лучше тем, что в отличие от Expand оно всегда содержит адрес группы в качестве #адреса получателя |
1 2 3 4 5 6 7 8 9 10 11 12 |
#По каждому адресу получателя проверяем в нашем словаре наличие такой строки. Если такая строка есть, #увеличиваем в ней значение счетчика на единицу, показывая общее количество писем на этот адрес Invoke-Command -ConfigurationName Microsoft.Exchange -ConnectionUri $Mailboxservers -Authentication Kerberos -Script { Get-MessageTrackingLog -EventId submit -ResultSize Unlimited |Select-Object -ExpandProperty recipients} | %{ if($dict[$_] -ge 0){$dict[$_]++ } } #Экспортируем ненулевые элементы в CSV, который затем прекрасно можно преобразовать в Excel, либо использовать дальше $dict.GetEnumerator() | ?{$_.value -ne 0} | select key,value | export-csv -NoTypeInformation C:\tmp\all2.csv |
За месяц письма приходили на 400 из 2800 адресов. Планируем понаблюдать квартал или полгода, после чего начать приборку.
Параллельно постараемся создать регламент работы с группами, описывающий их жизненный цикл.
До связи ;-).