Во времена Exchange 2010, если было необходимо найти и удалить письмо из почтовых ящиков пользователей использовался мега-командлет швейцарский нож Search-Mailbox, который позволял найти письма в нескольких почтовых ящиках, скопировать их куда надо и затем удалить. Этот командлет отлично работал при поиске и удалении, если необходимо было просмотреть несколько сотен почтовых ящиков. Если же ящиков было больше тысячи – начинались проблемы. Например, вот такие:

Единственное решение проблемы – разбивать ящики на группы и запускать поиск по группам меньшего размера. Например, как описано тут:
Get-Mailbox -Database databasename | Search-Mailbox -SearchQuery
'(from:spam@spamorg.com) AND (sent:1/1/2008..11/22/2012)' -DeleteContent -Force
Или даже так:
$allmbxinyourorg = Get-Mailbox -ResultSize unlimited
Foreach ($mbx in $allmbxinyourorg) {
Search-Mailbox -identity $mbx -SearchQuery '(from:spam@spamorg.com)
AND (sent:1/1/2008..11/22/2012)' -DeleteContent –Force
}
Проблему это решало, но поиск был ну очень уж долгий. То есть поиск по всей организации мог легко занимать несколько суток.
В Exchange 2013 была попытка уйти от этой проблемы с помощью командлета New-MailboxSearch. Но, к сожалению, он не позволял удалять письма, только найти и скопировать в ящик/выгрузить в pst-файл.
В Exchange 2016 сделана очередная попытка дать инструмент для быстрого поиска и удаления писем. Это командлеты New-ComplianceSearch и New-ComplianceSearchAction. Попытка получилась так себе, но местами очень даже ничего. Подробно процесс описан в следующих документах:
Use Compliance Search to search all mailboxes in Exchange 2016
Search for and delete messages in Exchange 2016
Но есть проблема – Compliance Search не умеет удалять письма. В общем эти документы стоит прочитать и забыть. Вот как нужно делать поиск и удаление в настоящей почтовой организации:
- Запускаем Compliance Search:
New-ComplianceSearch -Name Search1 -ExchangeLocation all -ContentMatchQuery 'from:"@corp.com"'
Start-ComplianceSearch -Identity Search1
- Получаем список почтовых ящиков, в которых есть нужные нам письма:
$search = Get-ComplianceSearch –Identity Search1
$results = $search.SuccessResults
$mailboxes = @()
$lines = $results -split '[\r\n]+'
foreach ($line in $lines)
{
if ($line -match 'Location: (\S+),.+Item count: (\d+)' -and $matches[2] -gt 0)
{
$mailboxes += $matches[1]
}
}
- Запускаем удаление писем из ящиков п.2:
$mailboxes | Get-Mailbox| Search-Mailbox -SearchQuery 'from:"@corp.com"' -DeleteContent -Force
Remove-ComplianceSearch –Identity Search1
Remove-MailboxSearch –Identity Search1-shadow
Первые два шага позволяют значительно сузить область поиска, что сильно скажется на времени работы итогового поиска через Search-Mailbox. Compliance Search на нескольких тысячах ящиков отрабатывает за пару минут. Если итоговый список ящиков для поиска получится в результате этого сократить даже вдвое, то это будет почти двухкратный выигрыш во времени.
Есть, правда, и в этой бочке мёда ложка дёгтя:
- Результат работы Compliance Search будет выглядеть в виде 1000 почтовых ящиков, отсортированных по количеству удовлетворяющих условию поиска писем. Если ящиков, в которых находится требуемое письмо больше 1000, то процедуру придётся повторить. До тех пор, пока не будут удалены все нужные письма.
Полезные ссылки:
Exchange Massive Search and Destroy & Quota control
Use Compliance Search to search all mailboxes in Exchange 2016
Search for and delete messages in Exchange 2016
Advanced Query Syntax
QueryString (QueryStringType)