В работе системного администратора бывают случаи проведения служебного расследования по деятельности сотрудников компании. Например, когда служба безопасности компании подозревает кого-то из работников в "сливе" информации конкурентам. Обычно в этом случае служба безопасности просит сделать выгрузку почтового ящика сотрудника в файл.
На первом этапе расследования службе безопасности требуется общая информация о деятельности сотрудника: контакты, названия писем, названия файлов на компьютере, распечатка звонков с корпоративного телефона и прочая общая информация.
То есть в случае с почтой полная выгрузка почтового ящика, которая описана в статье Exchange - Выгрузка почтового ящика в PST-файл не подходит. Необходимо просто сформировать таблицу из писем в почтовом ящике, а для этой задачи больше подходят программные средства, чем клиент Outlook и PST-файлы. Например, можно обработать почтовый ящик с помощью PowerShell.
Для подключения к почтовому серверу Exchange из PowerShell используются библиотеки Exchange Web Services Managed API 2.0, которые можно найти на сайте Microsoft. Подробные примеры использования Exchange Web Services (EWS) можно найти в блоге Glen Scales.
Для выгрузки почтового ящика с сервера Exchange в CSV-файл я написал PowerShell-скрипт, который получает письма из папок "Входящие" и "Отправленные", извлекает из писем необходимые поля ("От кого", "Кому", "Тема", "Дата", "Размер") и записывает результат в CSV-таблицу на рабочем столе текущего пользователя.
Итак, текст скрипта:
# Полезные статьи по теме Exchange Web Services
# Part 1 http://gsexdev.blogspot.ru/2012/01/ews-managed-api-and-powershell-how-to.html
# Part 2 http://gsexdev.blogspot.ru/2012/01/ews-managed-api-and-powershell-how-to_23.html
# Part 3 http://gsexdev.blogspot.ru/2012/02/ews-managed-api-and-powershell-how-to.html
# Part 4 http://gsexdev.blogspot.ru/2012/02/ews-managed-api-and-powershell-how-to_22.html
# Part 5 http://gsexdev.blogspot.ru/2012/05/ews-managed-api-and-powershell-how-to_28.html
# Part 6 http://gsexdev.blogspot.ru/2012/03/ews-managed-api-and-powershell-how-to_27.html
# Part 7 http://gsexdev.blogspot.ru/2012/04/ews-managed-api-and-powershell-how-to.html
# Part 8 http://gsexdev.blogspot.ru/2012/05/ews-managed-api-and-powershell-how-to.html
# Part 9 http://gsexdev.blogspot.ru/2012/05/ews-managed-api-and-powershell-how-to_28.html
# Part 10 http://gsexdev.blogspot.ru/2012/06/ews-managed-api-and-powershell-how-to.html
# Этот скрипт использует Microsoft Exchange Web Services Managed API 2.0
# http://www.microsoft.com/en-us/download/details.aspx?id=35371
# Почтовый ящик для выгрузки
# - перед открытием чужого почтового ящика необходимо выдать текущему пользователю полные права на него и
# перевойти в сессию почтового сервера
$MailboxName = "VBochkarev@domain.com"
# Очистка переменной ScriptResult
Remove-Variable ScriptResult -ErrorAction SilentlyContinue
$ScriptResult = @()
# Загрузка библиотек Microsoft Exchange Web Services DLL
$DllPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($DllPath)
# Подключение к серверу Exchange 2010 с текущими правами пользователя
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService `
([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
$WindowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$SidBind = "LDAP://<SID=" + $WindowsIdentity.user.Value.ToString() + ">"
$AceUser = [ADSI]$SidBind
$Service.AutodiscoverUrl($AceUser.mail.ToString())
# Открытие папки Inbox почтового ящика
$FolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId `
([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$FolderId)
# Создание фильтра поиска писем
$SearchFilterRead = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo `
([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $True)
$SearchFilterNotRead = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo `
([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $False)
$SearchFilterCollection = `
new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection `
([Microsoft.Exchange.WebServices.Data.LogicalOperator]::Or);
$SearchFilterCollection.add($SearchFilterRead)
$SearchFilterCollection.add($SearchFilterNotRead)
# Задание начальной позиции и количества писем в коллекции
$offset = 0;
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
# Задание расширенных свойств для подгрузки
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet `
([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
While (($results = $InboxFolder.FindItems($SearchFilterCollection, $view)).Items.Count -gt 0)
{
# Подгрузка расширенных свойств текущей коллекции писем
[Void]$service.LoadPropertiesForItems($results,$psPropset)
# Наполнение рабочей переменной свойствами писем из коллекции
ForEach ($item in $results)
{
$MailboxContent = New-Object System.Object
$MailboxContent | Add-Member -MemberType NoteProperty -Name Folder -Value $InboxFolder.Displayname
$MailboxContent | Add-Member -MemberType NoteProperty -Name FromAddress -Value $item.From.Address
$MailboxContent | Add-Member -MemberType NoteProperty -Name ToRecipients -Value `
([string]$item.ToRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name CcRecipients -Value `
([string]$item.CcRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name BccRecipients -Value `
([string]$item.BccRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name Subject -Value $item.Subject
$MailboxContent | Add-Member -MemberType NoteProperty -Name Received -Value $item.DateTimeReceived
$MailboxContent | Add-Member -MemberType NoteProperty -Name Sent -Value $item.DateTimeSent
$MailboxContent | Add-Member -MemberType NoteProperty -Name Size -Value $item.Size
$ScriptResult += $MailboxContent
}
# Перемещение курсора текущей позиции и настроек количества писем следующей коллекции
$offset += $results.Items.Count
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
}
# Получение списка подпапок
$fvFolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000);
$fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$ffResponse= $InboxFolder.FindFolders($fvFolderView);
# Получение писем подпапок
ForEach ($folder in $ffResponse.Folders)
{
# Задание начальной позиции и количества писем в коллекции
$offset = 0;
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
# Задание расширенных свойств для подгрузки
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet `
([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
While (($results = $InboxFolder.FindItems($SearchFilterCollection, $view)).Items.Count -gt 0)
{
# Подгрузка расширенных свойств текущей коллекции писем
[Void]$service.LoadPropertiesForItems($results,$psPropset)
# Наполнение рабочей переменной свойствами писем из коллекции
ForEach ($item in $results)
{
# Write Information regarding every e-mail in the folder
$MailboxContent = New-Object System.Object
$MailboxContent | Add-Member -MemberType NoteProperty -Name Folder -Value `
$InboxFolder.Displayname
$MailboxContent | Add-Member -MemberType NoteProperty -Name FromAddress -Value `
$item.From.Address
$MailboxContent | Add-Member -MemberType NoteProperty -Name ToRecipients -Value `
([string]$item.ToRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name CcRecipients -Value `
([string]$item.CcRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name BccRecipients -Value `
([string]$item.BccRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name Subject -Value $item.Subject
$MailboxContent | Add-Member -MemberType NoteProperty -Name Received -Value `
$item.DateTimeReceived
$MailboxContent | Add-Member -MemberType NoteProperty -Name Sent -Value $item.DateTimeSent
$MailboxContent | Add-Member -MemberType NoteProperty -Name Size -Value $item.Size
$ScriptResult += $MailboxContent
}
# Перемещение курсора текущей позиции и настроек количества писем следующей коллекции
$offset += $results.Items.Count
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
}
}
# Открытие папки SentItems почтового ящика
$FolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId `
([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems,$MailboxName)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$FolderId)
# Задание начальной позиции и количества писем в коллекции
$offset = 0;
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
# Задание расширенных свойств для подгрузки
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet `
([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
While (($results = $InboxFolder.FindItems($SearchFilterCollection, $view)).Items.Count -gt 0)
{
# Подгрузка расширенных свойств текущей коллекции писем
[Void]$service.LoadPropertiesForItems($results,$psPropset)
# Наполнение рабочей переменной свойствами писем из коллекции
ForEach ($item in $results)
{
# Write Information regarding every e-mail in the folder
$MailboxContent = New-Object System.Object
$MailboxContent | Add-Member -MemberType NoteProperty -Name Folder -Value $InboxFolder.Displayname
$MailboxContent | Add-Member -MemberType NoteProperty -Name FromAddress -Value $item.From.Address
$MailboxContent | Add-Member -MemberType NoteProperty -Name ToRecipients -Value `
([string]$item.ToRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name CcRecipients -Value `
([string]$item.CcRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name BccRecipients -Value `
([string]$item.BccRecipients) # преобразование массива в строку
$MailboxContent | Add-Member -MemberType NoteProperty -Name Subject -Value $item.Subject
$MailboxContent | Add-Member -MemberType NoteProperty -Name Received -Value $item.DateTimeReceived
$MailboxContent | Add-Member -MemberType NoteProperty -Name Sent -Value $item.DateTimeSent
$MailboxContent | Add-Member -MemberType NoteProperty -Name Size -Value $item.Size
$ScriptResult += $MailboxContent
}
# Перемещение курсора текущей позиции и настроек количества писем следующей коллекции
$offset += $results.Items.Count
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)
}
$ScriptResult | Export-Csv ((Get-Childitem env:USERPROFILE).Value + "\Desktop\PSOutput.csv") `
-Delimiter "`t" -Encoding UTF8
