Во времена 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)