среда, 12 января 2011 г.

Powershell и Exchange 5.5

Эта тема коснулась меня в свете миграции почтовых ящиков с Exchange 5.5 на Exchange 2003. Какой ужас, скажете вы, на дворе ведь 2011 год. К огромному моему сожалению это реальность. В то время как космические корабли бороздят … Большой театр, мы переезжаем с Exchange 5.5 на Exchange 2003.  Поэтому в дальнейшем я буду писать “старый” и “новый” сервер. Именно в кавычках. Мда. Но вместе с тем, к делу.

Процедура переезда достаточно простая. На текущем этапе просто происходит миграция ящиков. Пользователи пока остаются в старом домене, но, за счет доверительных отношений имеют доступ к новым ящикам. Однако, есть проблема. Когда пользователи “старого” сервера отправляют почту, используя свою адресную книгу, тем, кто уже переехал, возникает странная ситуация. Почта вроде бы отправилась, но у конечного абонента ее нет. Как тут быть? Решение вроде бы простое. Нужно создать контакт, который будет указывать на новый адрес в “новом” сервере. А затем подключить этот контакт как альтернативного получателя к тому почтовому ящику, чей пользователь уже на “новом” сервере. И все бы хорошо, но вот проблема – пользователей много, и создавать эти контакты вручную очень долго и нудно. Как тут быть? На помощь приходит, как ни странно, powershell и немного смекалки.

Exchange 5.5 поддерживает свой LDAP сервер и каталог, к которому можно добраться при помощи стандартных механизмов. Кроме того можно экспортировать и импортировать каталог в файл. Этим и воспользуемся. Прежде всего я экспортировал все почтовые ящики в один и одного контакта в другой csv файл. Затем, при помощи excel скопировал нужные данные из первого файла во второй так, чтобы при импорте файла с контактами получить эти контакты сразу в скрытом виде. В частности нужно изменить поле Directory Name, чтобы оно не совпадало с Directory Name у ящика. Ну, и импортировал полученный файл в отдельный контейнер под названием newDomainContainer. Осталось связать почтовые ящики и новые альтернативные контакты. Как выяснилось, для этого достаточно добавить к записи ящика атрибут "Alt-Recipient".

Что делаем.

$strLdapUser = "cn=administrator,dc=domain,cn=admin"
$strLdapPass = "password"

$mailRecipients = Get-Content c:\temp\exchange2.csv

foreach ($str in $mailRecipients){
$params = $str.split(",") #разделяем строку на куски
if ($params[5] -ne "Directory Name"){ #пропускаем заголовок 
$path = "LDAP://mailserver/cn="+$params[4]+",cn=Recipients,ou=domain,o=org"
$recipient = New-Object DirectoryServices.DirectoryEntry($path,$strLdapUser,$strLdapPass,0)
$recipient.Properties["Alt-Recipient"].Value = "cn="+$params[5]+",cn=newDomainContainer,cn=Recipients,ou=domain,o=org"
$recipient.CommitChanges()
$recipient.close()}
}
Скрипт не универсальный. Просто, так сказать, пруф оф концепт. На входе у него файл для импорта контактов. Поле с номером 5 – это Directory Name. Поле номер 4 - Alias Name. По нему происходит поиск в каталоге. Ну и собственно все. Для каждой строки происходит подключение к серверу и получение объекта почтового ящика. Затем у этого почтового ящика изменяется значение атрибута "Alt-Recipient". Если его изначально нет, нужно делать так:
$ds.Properties["Alt-Recipient"].Add("cn="+$params[5]+",cn=newDomainContainer,cn=Recipients,ou=domain,o=org" )
Вот. Затем CommitChanges сохраняет изменения назад.
Конечно, с точки зрения производительности тоже не лучший вариант. Само собой, что стоило вынести подключение за цикл. Но для этого нужно было бы разбираться с классами поиска. Я решил пойти более легким путем.
В общем, сомневаюсь, что кому-то пригодится, но на всякий случай пускай будет Улыбка

2 комментария:

Unknown комментирует...

Очень удивился увидев вместо import-csv и обращения по названиям полей, использование split и индексов полей. Зачем это? Не лучше ли так:
$mailRecipients = import-csv c:\temp\exchange.csv
foreach ($recipient in $mailRecipients)
{
$path = "LDAP://mailserver/cn=" + $recipient.server + ",cn=Recipients,ou=domain,o=org"
...
}

Unknown комментирует...

Посыпаю голову пеплом. Конечно лучше :). Что-то я на радостях от того, что мне не придется править это все вручную, совсем про import-csv и забыл. Поправлю скрипт. Спасибо за напоминание!