Exchange - Обработка почтового ящика средствами PowerShell

Реклама:
Записка от 26.05.2014

В работе системного администратора бывают случаи проведения служебного расследования по деятельности сотрудников компании. Например, когда служба безопасности компании подозревает кого-то из работников в "сливе" информации конкурентам. Обычно в этом случае служба безопасности просит сделать выгрузку почтового ящика сотрудника в файл.

Примечание. Выгрузка личной информации работника даже из корпоративной среды предприятия незаконна, если сам работник не дал на это согласие. Поэтому небходимо при приеме на работу ознакомить нового сотрудника с политиками безопасности компании и обязать подписать документ в котором определено, что работники дают согласие на доступ службы безопасности к личной информации сотрудника, хранящейся на рабочем компьютере и серверах компании, при расследовании инцидентов с письменного разрешения директора по персоналу.

На первом этапе расследования службе безопасности требуется общая информация о деятельности сотрудника: контакты, названия писем, названия файлов на компьютере, распечатка звонков с корпоративного телефона и прочая общая информация.

То есть в случае с почтой полная выгрузка почтового ящика, которая описана в статье 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
Вверх