Иногда требуется массово удалить письма из ящиков пользователей Exchange. К примеру, если прошла какая-то несанкционированная рассылка. Сегодня рассмотрим процесс удаления писем из ящиков всех пользователей Exchange от определённого отправителя.
Потребуются права:
- Mailbox Import Export
- Mailbox Search
Для начала требуется остановить источник спама, который нагрузил нашу почту. Если это внутренний сервис, то остановить его и прекратить спам. Если спам внешний, то настроить антиспам.
Очистка очереди
При рассылках большого объёма часть писем ещё не доставлена, требуется очистить очереди сообщений на почтовых серверах.
Remove-Message -Server server1 -Filter "FromAddress -eq 'evil@example.com'" -WithNDR $false
Remove-Message -Server server2 -Filter "FromAddress -eq 'evil@example.com'" -WithNDR $false
Очистка ящиков
После очистки очередей удалим доставленные письма из ящиков пользователей.
Первый способ
Можно использовать командлет Search-Mailbox, за один запуск можно удалить до 10000 писем.
WARNING: The Search-Mailbox cmdlet returns up to 10000 results per mailbox if a search query is specified. To return more than 10000 results, use the New-MailboxSearch cmdlet or the In-Place eDiscovery & Hold console in the Exchange Administration Center.
Пример удаления из всех ящиков:
Get-Mailbox –ResultSize unlimited | Search-Mailbox -SearchQuery 'from:"evil@example.com"' –DeleteContent –Force -confirm:$false
Пример удаления из одного ящика:
Search-Mailbox -Identity v.pupkin -SearchQuery 'from:"evil@example.com"' –DeleteContent –Force -confirm:$false
-SearchQuery позволяет формировать сложный поиск:
-SearchQuery {Subject:"RE:Ненужное письмо" OR body:"лишний текст"}
-SearchQuery 'hasattachment:true AND Size >20971520'
-SearchQuery 'from:"evil@example.com" AND to:"v.pupkin@example.com"'
-SearchQuery 'isread:false'
-SearchQuery 'size>200000'
-SearchQuery 'attachment:"virus.pdf"'
-SearchQuery 'attachment -like:"*.zip"'
-SearchQuery sent:22/02/2022
-SearchQuery {Received:20/06/2020..22/02/2022}
-SearchQuery {Received:> $('07/07/2021')}
Обойти ограничение на 10000 писем можно циклом, например:
for ($i = 1; $i -lt 10; $i++) {Get-Mailbox v.pupkin | Search-Mailbox -SearchQuery 'from:"evil@example.com"' -DeleteContent -Force}
Второй способ
Когда объёмы писем очень большие, приходится использовать другой командлет New-ComplianceSearch, за один запуск можно удалить до 10 писем из 50000 ящиков.
Создаём поиск сообщений, соответствующих требованиям для всех ящиков:
New-ComplianceSearch -Name "ContentSearch_for_delete" -ExchangeLocation all -ContentMatchQuery "from:evil@example.com"
Для одного ящика:
New-ComplianceSearch -Name "ContentSearch_for_delete" -ExchangeLocation v.pupkin@example.com -ContentMatchQuery "from:evil@example.com"
Посмотрим что нашлось:
Get-ComplianceSearch -Identity "ContentSearch_for_delete" | FL name,items,size,jobprogress,status
Name : ContentSearch_for_delete Items : 0 Size : 0 JobProgress : 0 Status : NotStarted
Поиск не запущен, запустим:
Start-ComplianceSearch -Identity "ContentSearch_for_delete"
Get-ComplianceSearch -Identity "ContentSearch_for_delete" | FL name,items,size,jobprogress,status
Name : ContentSearch_for_delete Items : 0 Size : 0 JobProgress : 0 Status : InProgress
Поиск в процессе работы, подождём:
Get-ComplianceSearch -Identity "ContentSearch_for_delete" | FL name,items,size,jobprogress,status
Name : ContentSearch_for_delete Items : 72212 Size : 937644300 JobProgress : 100 Status : Completed
Дожидаемся статуса Completed и прогресса 100%.
Get-ComplianceSearch -Identity "ContentSearch_for_delete" | Format-List
Создаём действие (удаление) для результатов поиска:
New-ComplianceSearchAction -SearchName ContentSearch_for_delete -Purge
Name SearchName Action RunBy JobEndTime Status ---- ---------- ------ ----- ---------- ------ ContentSearch_for_delete_Purge ContentSearch_for_delete Purge Олег 25.01.2024 13:52:28 Completed
В действии к названию добавляется постфикс "_Purge".
Посмотрим:
Get-ComplianceSearchAction -Identity "ContentSearch_for_delete_Purge" | Format-List
RunspaceId : 0e9b87e9-fbaf-4a4d-b66c-17216df267ac SearchName : ContentSearch_for_delete EstimateSearchRunId : 7c35912e-f966-4dd8-f501-08dc1dac14e7 EstimateSearchJobId : ca390215-f8ed-471e-fa2c-08dc1dabd094 ActionVersion : Results : Purge Type: SoftDelete; Item count: 0; Total size 0; Details: {} Errors : Action : Purge ValidDuration : 00:10:00 JobId : 8add4ad2-d4a6-45c2-702b-08dc1dacdbc0 Name : ContentSearch_for_delete_Purge CreatedTime : 25.01.2024 13:52:23 LastModifiedTime : 25.01.2024 13:52:23 JobStartTime : 25.01.2024 13:52:23 JobEndTime : 25.01.2024 13:52:28 Description : CreatedBy : Олег RunBy : Олег TenantId : 1851e79c-cc5f-4ef2-8b6e-8c373117de61 NumBindings : 1 Status : Completed ExchangeLocation : {oleg@example.com} PublicFolderLocation : SharePointLocation : OneDriveLocation : ExchangeLocationExclusion : PublicFolderLocationExclusion : SharePointLocationExclusion : OneDriveLocationExclusion : JobRunId : 83af0b97-a14d-42b7-0dfe-08dc1dacdbd3 Retry : False AllowNotFoundExchangeLocationsEnabled : False JobOptions : 0 JobProgress : 100 CaseId : CaseName : PagingState : Identity : 83af0b97-a14d-42b7-0dfe-08dc1dacdbd3 IsValid : True ObjectState : New
После очистки удаляем поиск:
Remove-ComplianceSearch -Identity "ContentSearch_for_delete"