Convertir buzones de Exchange 2003 en usuarios habilitados para correo en Exchange Online
Después de completar una migración almacenada provisionalmente, convierta los buzones locales en usuarios habilitados para correo para que los usuarios locales puedan conectarse automáticamente a sus buzones de correo en la nube.
¿Por qué convertir los buzones en usuarios habilitados para correo?
Debe convertir los buzones locales migrados en usuarios habilitados para correo (MEU) para poder administrar usuarios basados en la nube desde la organización local mediante Active Directory.
En este artículo se incluye un script de PowerShell que recopila información de los buzones basados en la nube y un script de Visual Basic (VB) que convierte buzones de Exchange 2003 en MEU. Cuando ejecuta este script, las direcciones del proxy del buzón basado en la nube se copian al MEU, que reside en Active Directory. Las propiedades del MEU permiten que la sincronización de directorios coincida con el MEU con su buzón de correo en la nube correspondiente.
Se recomienda convertir buzones locales en MEU para un lote de migración. Una vez finalizado un lote de migración provisional de Exchange, ha comprobado que todos los buzones del lote se han migrado correctamente y que la sincronización inicial de los elementos de buzón de correo en la nube se ha completado, convierta los buzones del lote de migración en MEU.
Script de PowerShell para recopilar datos de los buzones de nube
Use los scripts de esta sección para recopilar información sobre los buzones basados en la nube y convertir los buzones de Exchange 2003 en MEU.
El script de PowerShell recopila información de los buzones de correo en la nube y la guarda en un archivo CSV. Ejecute este script primero.
Copie el script en el Bloc de notas y guarde el archivo como ExportO365UserInfo.ps1.
Nota:
Antes de ejecutar el script, debe instalar el módulo de PowerShell Exchange Online. Para obtener instrucciones, consulte Instalación y mantenimiento del módulo de PowerShell Exchange Online. El módulo usa la autenticación moderna.
- Por lo general, puede usar el script tal como está si su organización es Microsoft 365 o Microsoft 365 GCC. Si su organización es Office 365 Germany, Microsoft 365 GCC High o Microsoft 365 DoD, tiene que modificar la línea
Connect-ExchangeOnline
en el script. En concreto, debe usar el parámetro ExchangeEnvironmentName y el valor adecuado para su organización. Para obtener más información, vea los ejemplos en Conexión a Exchange Online PowerShell.
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 Exchange Online PowerShell 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 Exchange Online Powershell Session." -ForeGroundColor Green
return
}
Disconnect-ExchangeOnline -Confirm:$false
}
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline
}
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-Premises 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
El script de Visual Basic convierte buzones de Exchange 2003 locales en MEU. Ejecute este script después de ejecutar el script de PowerShell para recopilar información de los buzones de correo en la nube.
Copie el script en el Bloc de notas y guarde el archivo como 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 usernames." & 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
¿Qué hacen los scripts?
ExportO365UserInfo.ps1
ExportO365UserInfo.ps1 es un script de PowerShell que se ejecuta en la organización basada en la nube para recopilar información sobre los buzones de correo en la nube que migró durante la migración provisional de Exchange. Usa un archivo CSV para examinar el lote de usuarios. Se recomienda usar el mismo archivo CSV de migración que usó para migrar un lote de usuarios.
Al ejecutar el script ExportO365UserInfo, se producen las siguientes acciones:
- Las siguientes propiedades se recopilan de los buzones de nube para los usuarios que aparecen en el archivo CSV de entrada:
- Dirección SMTP principal.
- Dirección SMTP principal del buzón local correspondiente.
- Otras direcciones proxy para el buzón de correo en la nube.
- DN de Exchange heredado
- Las propiedades que se han recopilado se guardan en un archivo CSV denominado Cloud.csv.
Exchange2003MBtoMEU.vbs
Exchange2003MBtoMEU.vbs es un script vb que se ejecuta en la organización local de Exchange 2003 para convertir buzones en MEU. Usa el archivo Cloud.csv generado por el script de PowerShell ExportO365UserInfo.ps1.
Al ejecutar el script de Exchange2003MBtoMEU.vbs, se producen las siguientes acciones para cada buzón que aparece en el archivo CSV de entrada:
- Recopila información del archivo CSV de entrada y del buzón local.
- Crea una lista de direcciones proxy del buzón en la nube y local para agregarla al MEU.
- Elimina el buzón local.
- Crea un MEU con las siguientes propiedades:
legacyExchangeDN: valor del buzón local.
mail: el SMTP principal del buzón de correo en la nube.
msExchMailboxGuid: valor del buzón local.
proxyAddresses: valores del buzón local y del buzón en la nube.
targetAddress: lee desde el buzón local; el valor es el SMTP principal del buzón de correo en la nube.
Importante
Para habilitar la retirada de Exchange Online a Exchange 2003, debe reemplazar el valor de la propiedad msExchMailboxGuid en el MEU por el GUID del buzón basado en la nube. Para obtener los valores GUID de los buzones basados en la nube y guardarlos en un archivo CSV, ejecute el siguiente comando de PowerShell Exchange Online:
Get-Mailbox | Select PrimarySmtpAddress,Guid | Export-csv -Path .\guid.csv
Este comando extrae la dirección SMTP principal y el GUID de todos los buzones de la nube en el archivo guid.csv y, después, guarda este archivo en el directorio actual.
En lugar de usar el archivo CSV de entrada para convertir un lote de buzones, puede ejecutar el script de Exchange2003MBtoMEU.vbs en el modo manual para convertir un buzón cada vez. Si elige este método, debe proporcionar los siguientes parámetros de entrada:
- El nombre distintivo (DN) del buzón local.
- La dirección SMTP principal del buzón de la nube.
- El DN heredado de Exchange para el buzón de la nube.
- Un nombre de controlador de dominio de su organización de Exchange 2003.
Pasos para convertir los buzones locales en MEU
Ejecute ExportO365UserInfo.ps1 en la organización de Exchange Online. Use el archivo CSV para el lote de migración como el archivo de entrada. El script crea un archivo CSV denominado Cloud.csv.
cd <location of the script> .\ExportO365UserInfo.ps1 <CSV input file>
Por ejemplo:
cd c:\data\scripts .\ExportO365UserInfo.ps1 .\MigrationBatch1.csv
Copie Exchange2003MBtoMEU.vbs y Cloud.csv en el mismo directorio de su organización local.
En su organización local, ejecute el siguiente comando:
cscript Exchange2003MBtoMEU.vbs -c .\Cloud.csv <FQDN of on-premises domain controller>
Por ejemplo:
cscript Exchange2003MBtoMEU.vbs -c .\Cloud.csv DC1.contoso.com
Para ejecutar el script en el modo manual, escriba el comando siguiente. Use espacios entre cada valor.
cscript Exchange2003MBtoMEU.vbs "<DN of on-premises mailbox>" "<Primary SMTP of cloud mailbox>" "<ExchangeLegacyDN of cloud mailbox>" <FQDN of on-premises domain controller>
Por ejemplo:
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
Compruebe que los nuevos MEU se hayan creado. En Usuarios y equipos de Active Directory, siga estos pasos:
Haga clic en Búsqueda de acciones>.
Haga clic en la pestaña Exchange.
Seleccione Mostrar solo destinatarios de Exchange y, después, seleccione Usuarios con una dirección de correo electrónico externa.
Haga clic en Buscar ahora.
Los buzones que se han convertido a MEU aparecen en Resultados de la búsqueda.
Use Usuarios y equipos de Active Directory, edición asi o Ldp.exe para comprobar que las siguientes propiedades MEU se rellenan con la información correcta:
- Legacyexchangedn
- msExchMailboxGuid*
- proxyAddresses
- targetAddress
* Como se ha explicado anteriormente, el script Exchange2003MBtoMEU.vbs conserva el valor msExchMailboxGuid del buzón local. Para habilitar el apagado de Microsoft 365 o Office 365 a Exchange 2003, debe reemplazar el valor de la propiedad msExchMailboxGuid en el MEU por el GUID del buzón basado en la nube.