Преобразование почтовых ящиков Exchange 2003 в пользователей, поддерживающих почту

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

Зачем преобразовывать почтовые ящики в пользователей, поддерживающих почту?

Если вы выполнили поэтапную миграцию Exchange для переноса локальных почтовых ящиков Exchange 2003 в Office 365 и хотите управлять облачными пользователями из локальной организации с помощью Active Directory, следует преобразовать локальные почтовые ящики в пользователей, поддерживающих почту (MEU).

Эта статья содержит сценарий Windows PowerShell, который собирает данные из облачных почтовых ящиков, а также сценарий Visual Basic (VB), который позволяет преобразовать почтовые ящики Exchange 2003 в MEU. При запуске этого сценария прокси-адреса из облачного почтового ящика копируются в MEU, который хранится в Active Directory. Кроме того, свойства MEU позволяют средству синхронизации Microsoft Online Services со службой каталогов (DirSync) сопоставить MEU с облачным почтовым ящиком.

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

Сценарий PowerShell для сбора данных из облачных почтовых ящиков

Указанные ниже сценарии можно использовать для сбора сведений об облачных почтовых ящиках и преобразования почтовых ящиков Exchange 2007 в MEU.

Следующий сценарий собирает данные облачных почтовых ящиков и сохраняет их в CSV-файл. Сначала запустите этот сценарий.

Скопируйте приведенный ниже сценарий в TXT-файл и сохраните его с именем ExportO365UserInfo.ps1.

Param($migrationCSVFileName = "migration.csv")
function O365Logon
{
#Check for current open O365 sessions and allow the admin to either use the existing session or create a new one
$session = Get-PSSession | ?{$_.ConfigurationName -eq 'Microsoft.Exchange'}
if($session -ne $null)
{
$a = Read-Host "An open session to Office 365 already exists. Do you want to use this session? Enter y to use the open session, anything else to close and open a fresh session."
if($a.ToLower() -eq 'y')
{
Write-Host "Using existing Office 365 Powershell Session." -ForeGroundColor Green
return
}
$session | Remove-PSSession
}
Write-Host "Please enter your Office 365 credentials" -ForeGroundColor Green
$cred = Get-Credential
$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic -AllowRedirection
$importresults = Import-PSSession $s
}

function Main
{

#Verify the migration CSV file exists
if(!(Test-Path $migrationCSVFileName))
{
Write-Host "File $migrationCSVFileName does not exist." -ForegroundColor Red
Exit
}

#Import user list from migration.csv file
$MigrationCSV = Import-Csv $migrationCSVFileName

#Get mailbox list based on email addresses from CSV file
$MailBoxList = $MigrationCSV | %{$_.EmailAddress} | Get-Mailbox
$Users = @()

#Get LegacyDN, Tenant, and On-Premise Email addresses for the users
foreach($user in $MailBoxList)
{
$UserInfo = New-Object System.Object

$CloudEmailAddress = $user.EmailAddresses | ?{($_ -match 'onmicrosoft') -and ($_ -cmatch 'smtp:')}
if ($CloudEmailAddress.Count -gt 1)
{
$CloudEmailAddress = $CloudEmailAddress[0].ToString().ToLower().Replace('smtp:', '')
Write-Host "$user returned more than one cloud email address. Using $CloudEmailAddress" -ForegroundColor Yellow
}
else
{
$CloudEmailAddress = $CloudEmailAddress.ToString().ToLower().Replace('smtp:', '')
}

$UserInfo | Add-Member -Type NoteProperty -Name LegacyExchangeDN -Value $user.LegacyExchangeDN
$UserInfo | Add-Member -Type NoteProperty -Name CloudEmailAddress -Value $CloudEmailAddress
$UserInfo | Add-Member -Type NoteProperty -Name OnPremiseEmailAddress -Value $user.PrimarySMTPAddress.ToString()

$Users += $UserInfo
}

#Check for existing csv file and overwrite if needed
if(Test-Path ".\cloud.csv")
{
$delete = Read-Host "The file cloud.csv already exists in the current directory. Do you want to delete it? Enter y to delete, anything else to exit this script."
if($delete.ToString().ToLower() -eq 'y')
{
Write-Host "Deleting existing cloud.csv file" -ForeGroundColor Red
Remove-Item ".\cloud.csv"
}
else
{
Write-Host "Will NOT delete current cloud.csv file. Exiting script." -ForeGroundColor Green
Exit
}
}
$Users | Export-CSV -Path ".\cloud.csv" -notype
(Get-Content ".\cloud.csv") | %{$_ -replace '"', ''} | Set-Content ".\cloud.csv" -Encoding Unicode
Write-Host "CSV File Successfully Exported to cloud.csv" -ForeGroundColor Green

}

O365Logon
Main

Следующий сценарий Visual Basic преобразует локальные почтовые ящики Exchange 2003 в MEU. Запустите этот сценарий после выполнения сценария для сбора сведений из облачных почтовых ящиков.

Скопируйте приведенный ниже сценарий в TXT-файл и сохраните его с именем Exchange2003MBtoMEU.vbs.

'Globals/Constants
Const ADS_PROPERTY_APPEND = 3

Dim UserDN
Dim remoteSMTPAddress
Dim remoteLegacyDN
Dim domainController
Dim csvMode
csvMode = FALSE
Dim csvFileName
Dim lastADLookupFailed


Class UserInfo
public OnPremiseEmailAddress
public CloudEmailAddress
public CloudLegacyDN
public LegacyDN
public ProxyAddresses
public Mail
public MailboxGUID
public DistinguishedName

Public Sub Class_Initialize()
Set ProxyAddresses = CreateObject("Scripting.Dictionary")
End Sub
End Class

'Command Line Parameters
If WScript.Arguments.Count = 0 Then
'No parameters passed
WScript.Echo("No parameters were passed.")
ShowHelp()
ElseIf StrComp(WScript.Arguments(0), "-c", vbTextCompare) = 0 And WScript.Arguments.Count = 2 Then
WScript.Echo("Missing DC Name.")
ShowHelp()
ElseIf StrComp(WScript.Arguments(0), "-c", vbTextCompare) = 0 Then
'CSV Mode
csvFileName = WScript.Arguments(1)
domainController = WScript.Arguments(2)
csvMode = TRUE
WScript.Echo("CSV mode detected. Filename: " & WScript.Arguments(1) & vbCrLf)
ElseIf wscript.Arguments.Count <> 4 Then
'Invalid Arguments
WScript.Echo WScript.Arguments.Count
Call ShowHelp()
Else
'Manual Mode
UserDN = wscript.Arguments(0)
remoteSMTPAddress = wscript.Arguments(1)
remoteLegacyDN = wscript.Arguments(2)
domainController = wscript.Arguments(3)
End If

Main()

'Main entry point
Sub Main

'Check for CSV Mode
If csvMode = TRUE Then
UserInfoArray = GetUserInfoFromCSVFile()
Else
WScript.Echo "Manual Mode Detected" & vbCrLf
Set info = New UserInfo
info.CloudEmailAddress = remoteSMTPAddress
info.DistinguishedName = UserDN
info.CloudLegacyDN = remoteLegacyDN
ProcessSingleUser(info)
End If

End Sub

'Process a single user (manual mode)
Sub ProcessSingleUser(ByRef UserInfo)

userADSIPath = "LDAP://" & domainController & "/" & UserInfo.DistinguishedName
WScript.Echo "Processing user " & userADSIPath
Set MyUser = GetObject(userADSIPath)
proxyCounter = 1
For Each address in MyUser.Get("proxyAddresses")
UserInfo.ProxyAddresses.Add proxyCounter, address
proxyCounter = proxyCounter + 1
Next
UserInfo.OnPremiseEmailAddress = GetPrimarySMTPAddress(UserInfo.ProxyAddresses)
UserInfo.Mail = MyUser.Get("mail")
UserInfo.MailboxGUID = MyUser.Get("msExchMailboxGUID")
UserInfo.LegacyDN = MyUser.Get("legacyExchangeDN")
ProcessMailbox(UserInfo)

End Sub

'Populate user info from CSV data
Function GetUserInfoFromCSVFile()

CSVInfo = ReadCSVFile()
For i = 0 To (UBound(CSVInfo)-1)
lastADLookupFailed = false
Set info = New UserInfo
info.CloudLegacyDN = Split(CSVInfo(i+1), ",")(0)
info.CloudEmailAddress = Split(CSVInfo(i+1), ",")(1)
info.OnPremiseEmailAddress = Split(CSVInfo(i+1), ",")(2)
WScript.Echo "Processing user " & info.OnPremiseEmailAddress
WScript.Echo "Calling LookupADInformationFromSMTPAddress"
LookupADInformationFromSMTPAddress(info)
If lastADLookupFailed = false Then
WScript.Echo "Calling ProcessMailbox"
ProcessMailbox(info)
End If
set info = nothing
Next

End Function

'Populate user info from AD
Sub LookupADInformationFromSMTPAddress(ByRef info)

'Lookup the rest of the info in AD using the SMTP address
Set objRootDSE = GetObject("LDAP://RootDSE")
strDomain = objRootDSE.Get("DefaultNamingContext")
Set objRootDSE = nothing
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand = CreateObject("ADODB.Command")
BaseDN = "<LDAP://" & domainController & "/" & strDomain & ">"
adFilter = "(&(proxyAddresses=SMTP:" & info.OnPremiseEmailAddress & "))"
Attributes = "distinguishedName,msExchMailboxGUID,mail,proxyAddresses,legacyExchangeDN"
Query = BaseDN & ";" & adFilter & ";" & Attributes & ";subtree"
objCommand.CommandText = Query
Set objCommand.ActiveConnection = objConnection
On Error Resume Next
Set objRecordSet = objCommand.Execute

'Handle any errors that result from the query
If Err.Number <> 0 Then
WScript.Echo "Error encountered on query " & Query & ". Skipping user."
lastADLookupFailed = true
return
End If

'Handle zero or ambiguous search results
If objRecordSet.RecordCount = 0 Then
WScript.Echo "No users found for address " & info.OnPremiseEmailAddress
lastADLookupFailed = true
return
ElseIf objRecordSet.RecordCount > 1 Then
WScript.Echo "Ambiguous search results for email address " & info.OnPremiseEmailAddress
lastADLookupFailed = true
return
ElseIf Not objRecordSet.EOF Then
info.LegacyDN = objRecordSet.Fields("legacyExchangeDN").Value
info.Mail = objRecordSet.Fields("mail").Value
info.MailboxGUID = objRecordSet.Fields("msExchMailboxGUID").Value
proxyCounter = 1
For Each address in objRecordSet.Fields("proxyAddresses").Value
info.ProxyAddresses.Add proxyCounter, address
proxyCounter = proxyCounter + 1
Next
info.DistinguishedName = objRecordSet.Fields("distinguishedName").Value
objRecordSet.MoveNext
End If

objConnection = nothing
objCommand = nothing
objRecordSet = nothing
On Error Goto 0

End Sub

'Populate data from the CSV file
Function ReadCSVFile()

'Open file
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFS.OpenTextFile(csvFileName, 1, false, -1)

'Loop through each line, putting each line of the CSV file into an array to be returned to the caller
counter = 0
Dim CSVArray()
Do While NOT objTextFile.AtEndOfStream
ReDim Preserve CSVArray(counter)
CSVArray(counter) = objTextFile.ReadLine
counter = counter + 1
Loop

'Close and return
objTextFile.Close
Set objTextFile = nothing
Set objFS = nothing
ReadCSVFile = CSVArray

End Function

'Process the migration
Sub ProcessMailbox(User)

'Get user properties
userADSIPath = "LDAP://" & domainController & "/" & User.DistinguishedName
Set MyUser = GetObject(userADSIPath)

'Add x.500 address to list of existing proxies
existingLegDnFound = FALSE
newLegDnFound = FALSE

'Loop through each address in User.ProxyAddresses
For i = 1 To User.ProxyAddresses.Count
If StrComp(address, "x500:" & User.LegacyDN, vbTextCompare) = 0 Then
WScript.Echo "x500 proxy " & User.LegacyDN & " already exists"
existingLegDNFound = true
End If
If StrComp(address, "x500:" & User.CloudLegacyDN, vbTextCompare) = 0 Then
WScript.Echo "x500 proxy " & User.CloudLegacyDN & " already exists"
newLegDnFound = true
End If
Next

'Add existing leg DN to proxy list
If existingLegDnFound = FALSE Then
WScript.Echo "Adding existing legacy DN " & User.LegacyDN & " to proxy addresses"
User.ProxyAddresses.Add (User.ProxyAddresses.Count+1),("x500:" & User.LegacyDN)
End If

'Add new leg DN to proxy list
If newLegDnFound = FALSE Then
'Add new leg DN to proxy addresses
WScript.Echo "Adding new legacy DN " & User.CloudLegacyDN & " to existing proxy addresses"
User.ProxyAddresses.Add (User.ProxyAddresses.Count+1),("x500:" & User.CloudLegacyDN)
End If

'Dump out new list of addresses
WScript.Echo "Original proxy addresses updated count: " & User.ProxyAddresses.Count
For i = 1 to User.ProxyAddresses.Count
WScript.Echo " proxyAddress " & i & ": " & User.ProxyAddresses(i)
Next

'Delete the Mailbox
WScript.Echo "Opening " & userADSIPath & " as CDOEXM::IMailboxStore object"
Set Mailbox = MyUser
Wscript.Echo "Deleting Mailbox"
On Error Resume Next
Mailbox.DeleteMailbox

'Handle any errors deleting the mailbox
If Err.Number <> 0 Then
WScript.Echo "Error " & Err.number & ". Skipping User." & vbCrLf & "Description: " & Err.Description & vbCrLf
Exit Sub
End If
On Error Goto 0

'Save and continue
WScript.Echo "Saving Changes"
MyUser.SetInfo
WScript.Echo "Refeshing ADSI Cache"
MyUser.GetInfo
Set Mailbox = nothing

'Mail Enable the User
WScript.Echo "Opening " & userADSIPath & " as CDOEXM::IMailRecipient"
Set MailUser = MyUser
WScript.Echo "Mail Enabling user using targetAddress " & User.CloudEmailAddress
MailUser.MailEnable User.CloudEmailAddress
WScript.Echo "Disabling Recipient Update Service for user"
MyUser.PutEx ADS_PROPERTY_APPEND, "msExchPoliciesExcluded", Array("{26491CFC-9E50-4857-861B-0CB8DF22B5D7}")
WScript.Echo "Saving Changes"
MyUser.SetInfo
WScript.Echo "Refreshing ADSI Cache"
MyUser.GetInfo

'Add Legacy DN back on to the user
WScript.Echo "Writing legacyExchangeDN as " & User.LegacyDN
MyUser.Put "legacyExchangeDN", User.LegacyDN

'Add old proxies list back on to the MEU
WScript.Echo "Writing proxyAddresses back to the user"
For j=1 To User.ProxyAddresses.Count
MyUser.PutEx ADS_PROPERTY_APPEND, "proxyAddresses", Array(User.ProxyAddresses(j))
MyUser.SetInfo
MyUser.GetInfo
Next

'Add mail attribute back on to the MEU
WScript.Echo "Writing mail attribute as " & User.Mail
MyUser.Put "mail", User.Mail

'Add msExchMailboxGUID back on to the MEU
WScript.Echo "Converting mailbox GUID to writable format"
Dim mbxGUIDByteArray
Call ConvertHexStringToByteArray(OctetToHexString(User.MailboxGUID), mbxGUIDByteArray)
WScript.Echo "Writing property msExchMailboxGUID to user object with value " & OctetToHexString(User.MailboxGUID)
MyUser.Put "msExchMailboxGUID", mbxGUIDByteArray

WScript.Echo "Saving Changes"
MyUser.SetInfo
WScript.Echo "Migration Complete!" & vbCrLf

End Sub

'Returns the primary SMTP address of a user
Function GetPrimarySMTPAddress(Addresses)
For Each address in Addresses
If Left(address, 4) = "SMTP" Then GetPrimarySMTPAddress = address
Next
End Function

'Converts Hex string to byte array for writing to AD
Sub ConvertHexStringToByteArray(ByVal strHexString, ByRef pByteArray)

Set FSO = CreateObject("Scripting.FileSystemObject")
Set Stream = CreateObject("ADODB.Stream")

Temp = FSO.GetTempName()
Set TS = FSO.CreateTextFile(Temp)

For i = 1 To (Len (strHexString) -1) Step 2
TS.Write Chr("&h" & Mid (strHexString, i, 2))
Next

TS.Close

Stream.Type = 1
Stream.Open
Stream.LoadFromFile Temp

pByteArray = Stream.Read

Stream.Close
FSO.DeleteFile Temp

Set Stream = nothing
Set FSO = Nothing

End Sub

'Converts raw bytes from AD GUID to readable string
Function OctetToHexString (arrbytOctet)

OctetToHexStr = ""
For k = 1 To Lenb (arrbytOctet)
OctetToHexString = OctetToHexString & Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
Next

End Function

Sub ShowHelp()

WScript.Echo("This script runs in two modes, CSV Mode and Manual Mode." & vbCrLf & "CSV Mode allows you to specify a CSV file from which to pull user names." & vbCrLf& "Manual mode allows you to run the script against a single user.")
WSCript.Echo("Both modes require you to specify the name of a DC to use in the local domain." & vbCrLf & "To run the script in CSV Mode, use the following syntax:")
WScript.Echo(" cscript Exchange2003MBtoMEU.vbs -c x:\csv\csvfilename.csv dc.domain.com")
WScript.Echo("To run the script in Manual Mode, you must specify the users AD Distinguished Name, Remote SMTP Address, Remote Legacy Exchange DN, and Domain Controller Name.")
WSCript.Echo(" cscript Exchange2003MBtoMEU.vbs " & chr(34) & "CN=UserName,CN=Users,DC=domain,DC=com" & chr(34) & " " & chr(34) & "user@cloudaddress.com" & chr(34) & " " & chr(34) & "/o=Cloud Org/ou=Cloud Site/ou=Recipients/cn=CloudUser" &
chr(34) & " dc.domain.com")
WScript.Quit

End Sub

Что делают сценарии?

ExportO365UserInfo.ps1

Это сценарий Windows PowerShell, который выполняется в облачной организации и собирает сведения об облачных почтовых ящиках, перенесенных в рамках поэтапной миграции Exchange. Для ограничения круга пользователей применяется CSV-файл. Мы рекомендуем использовать тот же CSV-файл, который использовался при миграции пакета пользователей.

При запуске сценария ExportO365UserInfo:

  • Следующие свойства собираются из облачных почтовых ящиков пользователей, указанных во входном CSV-файле:

    • Основной SMTP-адрес

    • Основной SMTP-адрес соответствующего локального почтового ящика

    • Другие прокси-адреса для облачного почтового ящика

    • Устаревшее различающееся имя Exchange

  • Собранные свойства сохраняются в CSV-файл с именем Cloud.csv.

Exchange2003MBtoMEU.vbs

Это сценарий VB, который выполняется в локальной организации Exchange 2003 и преобразует почтовые ящики в MEU. Он использует файл Cloud.csv, созданный сценарием ExportO365UserInfo.

При выполнении сценария Exchange2003MBtoMEU.vbs для каждого почтового ящика, указанного в CSV-файле, выполняется следующее:

  • Собираются данные из локального почтового ящика и входного CSV-файла.

  • Создается список прокси-адресов из локальных и облачных почтовых ящиков, которые нужно добавить в MEU.

  • Удаляется локальный почтовый ящик.

  • Создается MEU, который заполняется следующими свойствами:

    • legacyExchangeDN: значение из локального почтового ящика.

    • mail: основной SMTP-адрес облачного почтового ящика.

    • msExchMailboxGuid: значение из локального почтового ящика.

    • proxyAddresses: значения из локального и облачного почтовых ящиков.

    • targetAddress: основной SMTP-адрес облачного почтового ящика, полученный из локального почтового ящика.

      Важно : Чтобы обеспечить переход с Office 365 на Exchange 2003, необходимо заменить значение msExchMailboxGuid в MEU идентификатором GUID из облачного почтового ящика. Для получения идентификаторов GUID почтовых ящиков в облачной организации и сохранения их в CSV-файл выполните следующую команду PowerShell:

      Get-Mailbox | Select PrimarySmtpAddress, Guid | Export-csv -Path .\guid.csv

      Эта команда извлекает основной SMTP-адрес и GUID для всех облачных почтовых ящиков в файл guid.csv и сохраняет этот файл в текущей папке.

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

  • Различающееся имя (DN) локального почтового ящика.

  • Основной SMTP-адрес облачного почтового ящика.

  • Устаревшее различающееся имя Exchange облачного почтового ящика.

  • Имя контроллера домена в организации Exchange 2003.

Действия по преобразованию локальных почтовых ящиков в MEU

  1. Запустите ExportO365UserInfo в облачной организации. В качестве входного файла используйте CSV-файл пакета миграции. Сценарий создает CSV-файл с именем Cloud.csv.

    .\ExportO365UserInfo.ps1 <CSV input file>

    Например:

    .\ExportO365UserInfo.ps1 .\MigrationBatch1.csv

    В этом примере предполагается, что сценарий и входной CSV-файл находятся в одном и том же каталоге.

  2. Скопируйте Exchange2003MBtoMEU.vbs и Cloud.csv в один и тот же каталог в локальной организации.

  3. В локальной организации выполните следующую команду:

    cscript Exchange2003MBtoMEU.vbs –c .\Cloud.csv <FQDN of on-premises domain controller>

    Например:

    cscript Exchange2003MBtoMEU.vbs –c .\Cloud.csv DC1.contoso.com

    Для выполнения сценария вручную введите указанную ниже команду. Разделяйте значения пробелами.

    cscript Exchange2003MBtoMEU.vbs “<DN of on-premises mailbox>” “
    <Primary SMTP of cloud mailbox>” “<ExchangeLegacyDN of cloud mailbox>”
    <FQDN of on-premises domain controller>

    Например:

    cscript Exchange2003MBtoMEU.vbs “CN=Ann Beebe,
    CN=Users,DC=contoso,DC=com”
    “annb@contoso.onmicrosoft.com” “/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=d808d014cec5411ea6de1f70cc116e7b-annb” DC1.contoso.com
  4. Убедитесь, что были созданы MEU. В окне "Пользователи и компьютеры Active Directory" сделайте следующее:

    1. Щелкните Действие > Найти.

    2. Перейдите на вкладку Exchange.

    3. Выберите Показать только получателей Exchange и Пользователи с внешним адресом электронной почты.

    4. Нажмите кнопку Найти.

    Почтовые ящики, которые были преобразованы в MEU, будут указаны в списке Результаты поиска.

  5. Используйте средство "Пользователи и компьютеры Active Directory", "Редактирование ADSI" или Ldp.exe, чтобы убедиться, что указанные ниже свойства MEU заполнены правильными сведениями.

    • legacyExchangeDN

    • mail

    • msExchMailboxGuid*

    • proxyAddresses

    • targetAddress

    * Как объяснялось выше, сценарий Exchange2003MBtoMEU.vbs сохраняет значение msExchMailboxGuid из локального почтового ящика. Чтобы обеспечить переход с Office 365 на Exchange 2003, необходимо заменить значение msExchMailboxGuid в MEU идентификатором GUID из облачного почтового ящика.

Совершенствование навыков
Перейти к обучению
Первоочередный доступ к новым возможностям
Присоединиться к программе предварительной оценки Office

Были ли сведения полезными?

Спасибо за ваш отзыв!

Благодарим за отзыв! Возможно, будет полезно связать вас с одним из наших специалистов службы поддержки Office.

×