Exchange сервер позволяет администратору выполнять поиск по почтовым ящикам пользователей в базах и удалять из ящиков определенные письма (или другие элементы). Например, пользователь ошибся и случайно разослал приватные данные другим пользователям в организации и не успел отозвать сообщение в Outlook. Департамент защиты информации требует, чтобы вы, как администратор Exchange, удалили данное письмо у всех пользователей в вашем организации Exchange. В этой статье мы покажем, как с помощью PowerShell можно выполнять поиск по ящикам пользователей Exchange (по разным критериям) и удалять отдельные письма у конкретного пользователя или у всех пользователей Exchange. Описанные методики применимы для Exchange 2016, 2013 и 2010.
Назначаем разрешения для поиска по ящикам Exchange
Учетной записи администратора, который выполняет поиск и удаление элементов нужно назначить следующие роли:
- Mailbox Import Export
- Mailbox Search
Вы можете назначить роли через EAC или с помощью следующих команд PowerShell:
New-ManagementRoleAssignment -User itpro -Role "Mailbox Import Export"
New-ManagementRoleAssignment -User itpro -Role "Mailbox Search”
После назначения ролей нужно перезапустить консоль Exchange Management Shell.
Используем командлет Search-Mailbox для поиска и удаления писем в ящиках Exchange
Поиск писем в ящиках пользователей можно выполнить и через Exchange Control Panel / Exchange Admin Center, однако этот способ поиска довольно медленный и не позволяет удалять письма. Гораздо проще выполнить поиск с помощью PowerShell.
Для поиска сообщений в ящиках пользователей можно использовать командлет Search-Mailbox, который позволяет по определенным критериям найти письма во всех или конкретных ящиках, скопировать найденные элементы в другой ящик или удалить их.
Сначала разберемся, как выполнять поиск с помощью Search-Mailbox.
Для поиска в определенном ящике писем с определенной темой выполните команду:Search-Mailbox -Identity vasia -SearchQuery 'Subject:"Годовой отчет"'
Для поиска по всем ящикам в организации, воспользуйтесь командой:Get-Mailbox -ResultSize unlimited | Search-Mailbox -SearchQuery 'Subject:"Годовой отчет"'
Чтобы скопировать результаты поиска в определенный ящик и папку, используйте параметры TargetMailbox и TargetFolder. Таким образом после окончания поиска вы сможете с помощью Outlook или OWA вручную просмотреть найденные письма. Допустим, нам нужно выполнить поиск писем по списку пользователей (содержится в текстовом файле users.txt) и скопировать найденные письма в папку определённого ящика, выполните:
get-content users.txt | Get-Mailbox -ResultSize unlimited | Search-Mailbox -SearchQuery 'Subject:"Годовой отчет"' -TargetMailbox sec_mbx -TargetFolder "ExSearchFolder”
Параметр –LogOnly означает, что нужно выполнить только оценку результатов поиска, не копируя результаты поиска в целевой ящик и не удаляя элементы. При использовании этого аргумента на указанный целевой ящик будет отправлен отчет с результатами поиска. Отчет представляет собой заархивированный csv-файл, в котором перечислен список ящиков, соответствующих критериям поиска.
Вы можете оценить результаты поиска с помощью параметра –EstimateResultOnly, обратите внимание, что при использовании данного аргумента не нужно указывать целевой ящик и папку
Чтобы удалить найденные письма нужно использовать параметр –DeleteContent, чтобы убрать запросы на подтверждение удаления информации, добавьте параметр –Force.
Удалим все письма от пользователя vasia во всех ящиках на определенном сервере Exchnage:
Get-Mailbox –Server msk-mdb1 –ResultSize unlimited | Search-Mailbox -SearchQuery 'from:"vasia@winitpro.ru"' –DeleteContent –Force
Чтобы выполнить поиск только по удаленным элементам, добавьте параметр –SearchDumpsterOnly (чтобы исключить поиск по удаленным элементам, добавьте параметр -SearchDumpster:$false) . Если нужно исключить архив ящика, используйте параметр –DoNotIncludeArchive.
Примеры запросов SearchQuery на поиск писем в ящиках Exchange
Рассмотрим примеры запросов выборки почтовых элементов с помощью параметра SearchQuery. Параметр SearchQuery обрабатывает запросы на языке KQL (Keyword Query Language) — https://docs.microsoft.com/ru-ru/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference.
Удалим все письма с ключевым слово «Секрет» в теме от всех пользователей не из вашего домена:
Search-Mailbox -Identity vasia -SearchQuery 'Subject:"Секрет" and from<>”winitpro.ru”' -DeleteContent
Найти и удалить все письма с вложениями размером более 20Мб:
Search-Mailbox -Identity vasia -SearchQuery 'hasattachment:true AND Size >20971520' –DeleteContent
Можно одновременно искать по тексту в заголовке и в теме письма, например, найдем и удалим все письма, у которых в теме письма содержится фраза «Новый Год» или в тексте письма есть фраза «покупка коньяка».
Search-Mailbox vasia -SearchQuery {Subject:"RE:Новый Год" OR body:"покупка коньяка"} -DeleteContent -Force
Можно искать в ящиках определенные элементы, с помощью аргумента Kind, например,:
Собрания: -SearchQuery "Kind:meetings"
Контакты: -SearchQuery "Kind:contacts"
Или другие элементы:
- Email — письма
- Meetings — собрания
- Tasks — задачи
- Notes — заметке
- Docs – документы
- Journals — журналы
- Contacts — контакты
- IM – сообщения мессенджеров
Поиск писем по определенному отправителю и получателю
-SearchQuery 'from:"admin@winitpro.ru" AND to:"support@winitpro.ru"'
Можно искать письма с определенным файлом во вложении:
-SearchQuery 'attachment:"secret.pdf"'
Или по типу файла:
-SearchQuery 'attachment -like:"*.docx"'
Возможен поиск по дате отправки / получения писем, но тут есть несколько нюансов. При использовании дат в качестве критерия поиска нужно учитывать региональные настройки сервера Exchange. Например, дата 20 июля 2018 года может быть указана:
- 20/07/2018
- 07/20/2018
- 20-Jul-2018
- 20/July/2018
И если вы при выполнении команды Search-Mailbox вы получите ошибку “The KQL parser threw an exception…”, значит вы используете неверный формат времени.
Для поиска писем, отправленных в конкретный день, используйте запрос:
-SearchQuery sent:20/07/2018
Если нужно указать диапазон дат (поиск писем, полученных в указанный промежуток времени):
-SearchQuery {Received:20/06/2018..20/07/2018}
Еще один пример. Ищем письма, полученных до 7 июля:
-SearchQuery {Received:> $('07/07/2018')}
-SearchQuery {отправлено:"01/07/2018..20/07/2018" AND получено:"01/07/2018..20/07/2018}
Соответственно, нужно использовать такие конструкции в SearchQuery:
- кому:admin@winitpro.ru
- откого:»vasya@winitpro.ru»
- тема:»Tema такая»
ЗЫ. Именно за это я не люблю использовать русские версии продуктов!
Ограничения Search-Mailbox
У команды Search-Mailbox есть существенное ограничение она может вернут только 10000 элементов, после чего она вернет ошибку
Sending data to a remote command failed with the following error message: The total data received from the remote client exceeded allowed maximum. Allowed maximum is 524288000.
Поэтому, чтобы удалить большее количество элементов нужно запустить командлет Search-Mailbox несколько раз, либо разбивать ящик на группы по почтовым базам или серверам.
Get-Mailbox -Database mskdb | Search-Mailbox –SearchQuery 'from:spam@spammer.ru' -DeleteContent –Force
Другая проблема Search-Mailbox – низкая производительность. Поиск по большой организации может выполняться несколько суток.
Быстрый поиск и удаление писем в Exchange 2016 с помощью New-ComplianceSearch
В Exchange 2016 появился новый механизм для быстрого поиска и удаления писем в ящиках пользователей.
С помощью следующих команд можно существенно сузить область поиска:
New-ComplianceSearch -Name FastSearch1 -ExchangeLocation all -ContentMatchQuery 'from:"spammer@gmail.com"'
Start-ComplianceSearch -Identity FastSearch1
Данные команды отрабатывают на нескольких тысяч ящиков за несколько минут.
Получаем список ящиков, которые попадают под критерии поиска:
$search = Get-ComplianceSearch –Identity FastSearch1
$results = $search.SuccessResults
$mbxs = @()
$lines = $results -split '[\r\n]+'
foreach ($line in $lines)
{
if ($line -match 'Location: (\S+),.+Item count: (\d+)' -and $matches[2] -gt 0)
{
$mbxs += $matches[1]
}
}
Теперь можно запустить удалением писем с помощью Search-Mailbox только в найденных ящиках:
$mbxs | Get-Mailbox| Search-Mailbox -SearchQuery 'from:"spammer@gmail.com"' -DeleteContent –Force
Суммарное время поиска и удаления писем уменьшается в несколько раз, особенно в больших оргаизациях.
Теперь можно удалить результаты поиска:
Remove-ComplianceSearch –Identity FastSearch1
По поводу параметров -SearchDumpster и -SearchDumpsterOnly, думаю, стоит уточнить важный момент. Их использование подразумевает поиск не в папке Deleted, а в папке «Recoverable Items». Т.е. письма, которые уже отображаются в ящике.
Также я бы еще рассказал бы про ключ -IncludeUnsearchableItems, который включает в результаты поиска непроиндексированные объекты. Это очень даже важно, потому что те же письма с вложением *.pdf очень даже могут не проиндексироваться. И тогда в результате поиска мы ничего не увидим без этого ключа.
Спасибо! Дополнение по делу.
Не совсем понимаю механизм IncludeUnsearchableItems. Как можно искать по непроиндексированным элементам.
А собственно никак. При использовании данного ключа в результатах поиска добавится папка «Unsearchable» в которую попадут все непроиндексированные элементы не зависимо от критериев поиска. Поэтому нужно быть крайне осторожным при удалении.
Проверил у себя на Exchange 2016 SP8, получил
«New-ComplianceSearch : Имя «New-ComplianceSearch» не распознано как имя командлета…»
Вашей учетной записи долны быть назначены роли «Compliance Management» и «Discovery Management»
Здравствуйте! А где назначить эти роли? И как? Извините, я не могу ничего найти, админ уволился, доступы к серверам есть, а где чего делать, непонятно.
Какя версия Exchange?
Состав роли можно получить так:
Get-RoleGroupMember "Discovery Management"
Можно назначить роль через командную строку PowerShell Exchange Management Shell:
Add-RoleGroupMember "Discovery Management" -Member admin1
Отправил пьсмо, сделал все по инструкции(новый, быстрый способ), письмо не удалилось…
Может оно еще не проиндескировано?
Куда вставлять ключ IncludeUnsearchableItems ?
Добрый день!
Спасибо за статью.
Подскажите плиз, так уж сложилось, что Exchange 2010 русский. И -searchquery keywords приходится вводить русские. Вот не могу найти аналог Body: на русском, т.е. нужно найти определенный текст в теле письма и во вложениях.
Спасибо!
К сожалению у меня английская версия Exchange, проверить сам не могу.
Попробуйте «тело»: -SearchQuery ‘Тело:»Совещание»‘
Да, и есть ли какой способ удалять найденные через ECP письма в ящиках пользователей? иногда это удобно, можно быстро просмотреть контент.
-SearchQuery {Received:20/06/2018..20/07/2018}
как быть , если нужно указать промежуток времени+отправитель + поиск по всем почтовым ящикам?
хочу что-то типа такого:
Get-Mailbox -ResultSize unlimited | Search-Mailbox -SearchQuery {Received:»20/06/2018 1:10 PM..20/07/2018 1:30 PM» AND ‘from:»senser@xxx.com»‘} TargetMailbox adminpost -TargetFolder «SearchAndDeleteLog» -LogOnly -LogLevel
Тут все зависит от формата даты в вашей системе. Попробуйте такой формат поиска:
-SearchQuery {Received:"20/06/2018 1:10..20/07/2018 13:30" AND from:senser@xxx.com}
Есть вообще где-нибудь библиотека русских ключе в аргументах KQL?
К сожалению, я тоже не встречал таблицу соотвествия русских и английских аргументов KQL. Вот таблица списка индексируемых свойств, которые можно использовать в поиске Search-Mailbox: https://docs.microsoft.com/en-us/exchange/message-properties-indexed-by-exchange-search-exchange-2013-help
Можно по смыслу подбирать, но очень трудоемко.
Это ксати еще один аргумент в пользу того, что нужно использовать английские версии серверного ПО.
Здравствуйте! Стоит задача по выявлению сотрудников, отсылающих письма на сторонние ящики. Как это можно сделать?
Думаю можно использовать примерно такой запрос для получения всех писем, отправленных не локальным получателям в домене (на внешние адреса)
Get-Mailbox -Identity username | New-MailboxSearch -Name FindExternalEmails -TargetMailbox adminmail| Where {$_.Recipients -notlike "*@winitpro.ru"}
либо для начала проверить транспортные журналы на отправление наружу:
Get-TransportServer -Identity exchangeHUBname | Get-MessageTrackingLog -resultsize unlimited |where-object {$_.Recipients -notlike "@winitpro.ru" AND $_.EventId -eq "Send"} | ft
Да просто запретите этим пользователям такую отправку
При использовании ключа –EstimateResultOnly отображаются результаты для всех почтовых ящиков. Возможно ли отфильтровать вывод –EstimateResultOnly таким образом, чтобы отображались результаты поиска только для тех почтовых ящиков, для которых значение ResultItemsCount отлично от нуля?
Попробуйте так:
Search-Mailbox ...... –EstimateResultOnly | Where-Object ResultItemsCount -gt 0
При использовании New-ComplianceSearch получаю ошибку WriteError: (:) [], AggregateException. Информации вообще никакой нет, может. Полный запрос New-ComplianceSearch -Name «Remove» -ExchangeLocation all -ContentMatchQuery ‘тема:»Test Test»‘.
Доброго дня.
Большинскво команд заканчивается так:
Get-Mailbox -Database mskdb | Search-Mailbox –SearchQuery ‘Subject:»Немедленно смените пароль!»‘ -TargetMailbox admin -TargetFolder «ExSearchFolder”
Ключевое слово property не поддерживается.
+ CategoryInfo : InvalidArgument: (:) [], ParserException
+ FullyQualifiedErrorId : EBF20523
–SearchQuery Subject надо на русском получается?
В русской версии Exchange все параметры поиска SearchQuery нужно писать по-русски. Т.е. «Тема» вместо «Subject» и т.д.
Get-Mailbox -ResultSize unlimited | Search-mailbox -SearchQuery {‘subject:»RE: у кого есть» and Received:»26/12/2019″‘} -DeleteContent -Force
На Exchange 2013 данная команда отработала все письма содержавшие «RE:» и дату, а не «RE: у кого есть» и дату . Встречал ли кто такое? Что я сделал не так. ((((( Грухнулись письма содержащие RE: на 26 число.
А у вас в принципе запрос
-SearchQuery {'subject:"RE: у кого есть"')
находит что-то?Добрый день.
Подскажите пожалуйста, как запустить команду на поиск по списку серверов?
Укажите список mailbox серверов в первой переменной. Затем используйте цикл foreach для перебора серверов:
$mbx="mbx1","mbx2"
Foreach ($mb in $mbx)
{
Get-Mailbox -Server $mb -ResultSize | Search-Mailbox -SearchQuery ....
}
Каким образом следует действовать, если нужно найти все письма от определённых отправителей/получателей в почтовых ящиках пользователей и произвести выгрузку их содержимого в каком либо виде?
Search-Mailbox все это умеет. Сфомируйте критерии поиска писем и выполните Search-Mailbox с -TargetMailbox sec_mbx -TargetFolder «ExSearchFolder”. Все письма, которые соотвествуют критерию будут скопированы в указанную папку указанного ящика.
«New-ComplianceSearch -Name FastSearch1 -ExchangeLocation all -ContentMatchQuery ‘from:test@gmail.com’
Не удается выполнить эту задачу. Причина: Не удалось получить существующего пользователя. Повторите попытку позже.»
Почему может быть такая ошибка
Коллеги на форуме подсказывают что у учетки под которой происходит поиск обязательно должен быть почтовый ящик, но разве правильно когда у привиллигерованой учетки есть почтовый ящик?
Ну, если создание ящика решает проблему с кмндлетом New-ComplianceSearch, то создавайте его и не мучайтесь. Для чего нужен именно ящик знает только microsoft. У меня по крайней мере у учетной записи админа exchange ящик есть, были еще несколько командлетов, которые без ящика не работали.
А подскажите как из поиска по ключевому слову по всей организации исключить некоторых пользователей.
вот пример по всем ящикам
Get-Mailbox -ResultSize unlimited | Search-Mailbox -SearchQuery ‘пример’ -EstimateResultOnly
А как из этого исключить нескольких пользователей?
Если нужно исключить пару пользователей, можно так:
Get-Mailbox -ResultSize unlimited| Where-Object {$_.PrimarySmtpAddress -ne 'user1n@winitpro.ru' -AND $_.PrimarySmtpAddress -ne 'user3n@winitpro.ru' }| Search-Mailbox -SearchQuery ‘пример’ -EstimateResultOnly
Но это очень медленно будет работать, с фильтром наверно побыстрее:
Get-Mailbox -Filter {(PrimarySmtpAddress -ne 'user1n@winitpro.ru') -or (PrimarySmtpAddress -ne 'use2n@winitpro.ru'}
Спасибо!! , первый способ работает — второй нет)))
А можно ли использовать тут не параметр PrimarySmtpAddress c e-mail, а название почтового ящика, как в параметре Identyty?
Да, для поиска можно использовать любой атрибут ящика Exchange
Search-Mailbox -Identity username -SearchQuery ‘Subject:»some words» doesn’t work!
>>The target mailbox or .pst file path is required.
For what? Which .pst? I just want some mails to be displayed in EMS windows, I don’t need target mailbox…
Search-Mailbox can’t return found items directly to EMS. You can only export results to some folder on a target mailbox (you can use your own mailbox) or to a pst file.
Здравствуйте.
Как посмотреть историю выполненных команд на exchange?
Вы про аудит действий администраторов? Нужно настраивать Set-AdminAuditLogConfig. Если нужно аудировать все команды:
Set-AdminAuditLogConfig -AdminAuditLogCmdlets *
Set-AdminAuditLogConfig -AdminAuditLogEnabled $true
Get-history
Добрый День !
Такая вот ситуевина. Отправляю тестовое письмо на ящик, затем запускаю поиск в по ящику командой
Search-Mailbox -Identity user1 -SearchQuery {from:test@gmail.com And received:10-02-2021} -EstimateResultOnly
Но в ответ получаю нули. А если запустить вот такую без даты
Search-Mailbox -Identity user1 -SearchQuery from:test@gmail.com -EstimateResultOnly
То находит, формат даты пробовал разный все равно с указанием дат по нулям.
Логический оператор большими буковками AND OR NOT. Пардон за спешку, сам тупанул )