Известно, что при необходимости, мы можем разрешить кому-либо отправлять письма от имени нужного почтового ящика. Для этого используется командлет Add-ADPermission:

Add-ADPermission "Mailbox" -User "DomainUser" -ExtendedRights "Send As"

Менее известно, что при наличии необходимых обновлений для Outlook 2003/2007/2010 становился доступен ключ DelegateSentItemsStyle в ветке реестра HKСUSoftwareMicrosoftOfficexx.0OutlookPreferences, который позволял при такой отправке помещать письма не в папку Sent Items отправляющего пользователя, а в папку Sent Items нужного почтового ящика.

И уж почти не известно, что с выходом Rollup Update 4 для Exchange 2010 SP2 появилась возможность управлять этим процессом с сервера, с помощью следующих командлетов Get-MailboxSentItemsConfiguration и Set-MailboxSentItemsConfiguration. Первый командлет выводит текущие настройки процесса обработки исходящих писем в случае отправки от чужого почтового ящика:

[PS] C:>Get-MailboxSentItemsConfiguration tempstas

RunspaceId                  : 537ce593-b8e1-4110-b99f-076e92f6f1d2
SendAsItemsCopiedTo         : Sender
SendOnBehalfOfItemsCopiedTo : Sender
Identity                    :
IsValid                     : True

С помощью командлета Set-MailboxSentItemsConfiguration мы можем значения этих параметров SendAsItemsCopiedTo и SendOnBehalfOfItemsCopiedTo поменять на SenderAndFrom. Эти параметры могут принимаать следующие значения:

  • Sender. Значение по умолчанию. Указывает на то, что при отправке от имени чужого почтового ящика письма будут попадать в папку Sent Items отправителя.
  • SenderAndFrom. Указывает на то, что при отправке от имени чужого почтового ящика письма будут попадать в папку Sent Items как отправителя письма, там и того ящика, от имени которого письмо отсылается.
  • From. Это особо секретный параметр. Пока, что его нет в документации и применять его не рекомендуется. При последующей доработке будет использоваться для размещения отправленного письма в папку Sent Items ящика от имени которого отправляем письмо. Но на текущий момент эффект от этого ключа такой же как и от SenderAndFrom.

Самое главное – оба эти командлета применяются к ящику, от имени которого необходимо будет отправлять письма. В дальнейшем, все, кто имеет права на отправку получат описанное выше поведение почтового клиента. Небольшая ложка дёгтя – при наличии на клиенте ключа DelegateSentItemsStyle имеющего значение 1 эти новые настройки срабатывать не будут.

Но и это ещё не всё! Доступ к этим настройкам имеется через OWA:

Написано на основе записи.

Задача – выгрузить список общих (с которыми работают несколько пользователей) ящиков Exchange 2010 с:

  • почтовыми адресами,
  • списком тех, у кого есть полный доступ на ящик,
  • менеджером,
  • размером ящика

Итоговый вывод примерно следующий будет:

"MailboxName1":"Email1":"FAUser1;FAUser2;":"Manager1":"MBSize1"
"MailboxName2":"Email2":"FAUser3;FAUser4;":"Manager2":"MBSize2"
....

Первые два столбца получаются через

Get-Mailbox -Database "Database" -ResultSize unlimited | Select DisplayName,
PrimarySmtpAddress

Мы предполагаем, что общие ящики находятся в одной базе, и кроме них в этой базе других ящиков (пользовательских) нет. Список пользователей, имеющих права доступа мы можем получить, используя командлет Get-MailboxPermission. Причём, нас интересуют только пользователи, которым Full Access дан непосредственно на сам общий ящик, а не на объект, находящийся выше по иерархии (то есть отфильтровываем наследуемые записи для которых параметр IsInherited принимает значение $true). Заодним убираем объект NT AUTHORITYSELF.

$tmpUsersPermissions = Get-Mailbox $_ | Get-MailboxPermission |
?{($_.IsInherited -eq $false) -and ($_.user -notlike "NT AUTHORITYSELF")} |
Select User

Далее массив получённых учётных записей надо “склеить”:

$UserPermissionString = "";
foreach ($UserPermission in $tmpUsersPermissions) {
     $UserPermissionString = $UserPermissionString + $UserPermission.User + "; "}

В итоге, в переменной $UserPermissionString окажется требуемый список пользователей с правами Full Access на ящик.

Следующий, интересующий нас объект – менеджер ящика (на самом деле учётной записи, к которой прикреплён ящик). Так как сам почтовый ящик уже помещён в переменную $_, то можно её использовать для того, чтобы вытащить через Get-User из параметра Manager учётную запись менеджера почтового ящика

(Get-User $_).Manager.Name

Аналогично, через Get-MailboxStatistics и переменную $_ получаем размер ящика. Для уменьшения количества цифр конвертируем его в мегабайты

($_ | Get-MailboxStatistics).TotalItemSize.Value.ToMB()

Теперь осталось всё собрать в одну строку и вывести в csv-файл. В итоге получается примерно следующая конструкция

Get-Mailbox -Database "Database" -ResultSize unlimited | Select DisplayName,
PrimarySmtpAddress,
@{Name="FullAccess";expression={
$tmpUsersPermissions = Get-Mailbox $_ | Get-MailboxPermission |
?{($_.IsInherited -eq $false) -and ($_.user -notlike "NT AUTHORITYSELF")} |
Select User;
$UserPermissionString = "";
foreach ($UserPermission in $tmpUsersPermissions) {
     $UserPermissionString = $UserPermissionString + $UserPermission.User + "; "};
$UserPermissionString;}},
@{Name="Manager";expression={(Get-User $_).Manager.Name}},
@{Name="MailboxSize";expression={
($_ | Get-MailboxStatistics).TotalItemSize.Value.ToMB()}} |
Export-Csv c:Tempmailboxes.txt -Delimiter :

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

Так как в заголовке указано, что данные предназначены для аудита, то список для выгрузки можно дополнить, например, списком тех у кого есть права на отсылку, или датой последнего изменения.

Некоторое время назад получил крайне экзотическую задачу – необходимо было посчитать число писем отправленных и полученных некоторой группой сотрудников за каждый день прошедшего месяца и вывести эту информацию в виде удобном для обработки. Так как необходимо посчитать число писем за определённый день, то необходимо использовать командлет  Get-MessageTrackingLog, причём считать будем только события “RECEIVE”. Письма, в которых сотрудник будет указан в получателях, считаются им полученными, в которых отправителем – отправленными (Капитан Очевидность умер от зависти). Данные можно поместить в две переменные $Received и $Sent:

# block1
$Received = Get-TransportServer | Get-MessageTrackingLog -ResultSize unlimited
-Start $TmpDate -End $TmpDate.AddDays(1) -EventId "RECEIVE" -Recipients $SMTP |
Measure-Object;

$Sent = Get-TransportServer | Get-MessageTrackingLog -ResultSize unlimited
-Start $TmpDate -End $TmpDate.AddDays(1) -EventId "RECEIVE" -Sender $SMTP |
Measure-Object;

Здесь в переменных $TmpDate будет находиться дата, на которую мы считаем письма, а в $SMTP – адрес конкретного сотрудника. Для удобства хранения полученной информации создадим новый объект, который будет хранить адрес сотрудника, указанную дату, число полученных и отправленных писем (спасибо Вадимсу Подансу за подсказку, как это можно сделать):

# block 2
$tmpObject = New-Object psobject -Property @{
smtp = $SMTP;
date = $TmpDate.ToShortDateString();
rcount = $Received.Count;
scount = $Sent.Count;  }

Осталось указанное выше завернуть в цикл и с шагом в один день, до тех пор, пока не упрёмся в последний нужный день посчитать письма:

$StartDate = Get-Date "01.01.2012";
$EndDate = $StartDate.AddMonths(1);
# block 3
$TmpDate = $StartDate;
While ($TmpDate -ne $EndDate) {
<block 1>
<block 2>
$TmpDate = $TmpDate.AddDays(1);
$tmpObject | select smtp, date, rcount, scount; }

Здесь $StartDate – дата, с которой начинаем считать (в эту переменную можно значение ввести через Get-Date, как это сделал я, можно через Read-Host, можно любым другим способом), $EndDate – дата, на которой заканчиваем считать письма (у меня она смещена на один месяц, по сравнению со $StartDate, но можно её указать любым другим способом). В конце собранные данные выводятся на экран, но вывод можно сделать в файл (File-Out, например).

Осталось теперь данные собрать по всем сотрудникам. Для этого их почтовые адреса передаём в переменную-массив и по каждому члену массива делаем обсчёт.

$SMTPs = "user1@domain.com", "user2@domain.com";
ForEach ($SMTP in $SMTPs) {
<block 3>; }

Почтовые адреса в переменную можно передать прямым списком (как написано у меня), можно импортировать из csv-файла через Import-Csv. Итоговый скрипт выглядит следующим образом:

$StartDate = Get-Date "01.05.2012";
$EndDate = $StartDate.AddMonths(1);
$SMTPs = "user1@domain.com", "user2@domain.com";
ForEach ($SMTP in $SMTPs) {
$TmpDate = $StartDate;
While ($TmpDate -ne $EndDate) {
$Received = Get-TransportServer | Get-MessageTrackingLog -ResultSize unlimited
-Start $TmpDate -End $TmpDate.AddDays(1) -EventId "RECEIVE" -Recipients $SMTP |
Measure-Object;

$Sent = Get-TransportServer | Get-MessageTrackingLog -ResultSize unlimited
-Start $TmpDate -End $TmpDate.AddDays(1) -EventId "RECEIVE" -Sender $SMTP |
Measure-Object;

$tmpObject = New-Object psobject -Property @{
smtp = $SMTP;
date = $TmpDate.ToShortDateString();
rcount = $Received.Count;
scount = $Sent.Count;  }
$TmpDate = $TmpDate.AddDays(1);
$tmpObject | select smtp, date, rcount, scount; } }

Есть одна тонкость, которую следует помнить – данные в логах по умолчанию хранятся за последние 30 дней. Поэтому, чтобы иметь возможность посчитать письма на более ранние даты необходимо срок хранения увеличить, например до 90 дней:

Set-TransportServer -Identity ServerName -MessageTrackingLogMaxAge 90.00:00:00

Недавно успешно завершился кейс с крайне странной проблемой, которая заключалась в следующем: после миграции почтового ящика пользователя с Exchange 2007 на Exchange 2010 клиент Lync перестал сохранять сообщения в папку Conversation History. При этом, все эти сообщения вполне успешно складировались в папку %user%AppDataLocalMicrosoftCommunicator%sip_address%History Spooler, но не пересылались в почтовый ящик.

В ходе борьбы с проблемой случайно выяснилось, что когда в ящике содержится чуть меньше тысячи папок, то сохранение истории разговоров начинает работать. При создании нескольких дополнительных папок (и при превышении порога в тысячу папок) сохранение перестаёт работать. Начинаем подозревать throttling policy. Политика throttling policy, применяемая по умолчанию ко всем почтовым ящикам, содержит интересный ключ EWSFindCountLimit, который равен 1000!

Дальнейшая операция создания и назначения новой throttling policy и задания в ней EWSFindCountLimit в NULL закрыло проблему. Скрипт следующий:

New-ThrottlingPolicy -Name "EWSFindCountLimit unlimited" -EWSFindCountLimit $null
Set-Mailbox -Identity UserName -ThrottlingPolicy "EWSFindCountLimit unlimited"

В процессе сохранения истории разговоров клиент Lync пробует использовать EWS. Если не получается использовать EWS, то используется MAPI. В процессе использования EWS, по всей видимости, используется функция FindFolder для перечисления папок ящика. Она как раз и возвращает значение, которое фильтруется параметром EWSFindCountLimit. Соответственно, при возвращаемом значении, которое больше тысячи, мы получаем ошибку и невозможность сохранять историю разговоров. Так ли это или нет, достоверно утверждать не могу, так как в открытых источниках отсутствует информация о том как клиент Lync через EWS сохраняет историю разговоров в папку Conversation History (либо я не смог найти эту информацию).

Дополнительные ссылки по проблеме:
Throttling Policies and the EWSFindCountLimit
Another fix for Lync Conversation History problems
Lync 2010 and Outlook 2010 cannot save conversation history

В блоге Тони Редмонда попалась замечательная табличка, описывающая направления развития системы в зависимости от выпускаемой версии. Выглядит она следующим образом:

Версия Область технологий Воздействие Размер ящиков
Exchange 2000/2003 SAN и кластеры Рост количества пользователей 100MB
Exchange 2007 PKI и пространства имён Рост количества устройств и способов доступа 500MB
Exchange 2010 Балансировка и высокая доступность (CAS/ISA) BYOD – возможность подключения любых устройств пользователя 5GB
Exchange 2013 Выполнение требований законодательства, поиск данных, обработка больших массивов неструктурированных данных Тесная интеграция с  SharePoint и Lync 100GB

Комментарии:

  • Область технологий – то что требовалось хорошо знать при проектировании решений
  • Воздействие – те задачи/условия, которые повлияли на формирование области технологий
  • Размер ящиков – рекомендуемые ограничения по размерам почтовых ящиков пользователей
  • В оригинале область технологий для Ex2013 выглядит следующим образом – “Compliance, discovery, data mining”

Так что, добро пожаловать в эпоху взрывного роста данных и их интеллектуальной обработки.