Forum Discussion
Migrating On-Prem Distribution Groups to Exchange Online in Hybrid Mode
######## Global Variables ############
Set-Location -Path $env:USERPROFILE\Documents
#Get-PSSession | Remove-PSSession
$UserCredential = Get-Credential
$ListOfGroupsToMigrate = Import-csv .\GroupMigration.csv
#######################################
$ListOfGroupsToMigrate | ForEach-Object {
$SingleGroupToMigratePSMTP = $_.GroupEmailAddress
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://ExhangeServerFQDN.com/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session -Allowclobber
$distrotomovedetails = Get-DistributionGroup -Identity $SingleGroupToMigratePSMTP
$distrotomovedetails | Export-csv .\singlegroupdetailsbeforedelete.csv -NoTypeInformation
$distrotomovedetails | ForEach-Object{
$DistributionGroupName = $_.PrimarySmtpAddress
Get-DistributionGroupMember -Identity $DistributionGroupName | ForEach-Object{
[PSCustomObject]@{
DistributionGroup = $DistributionGroupName
MemberName = $_.DisplayName
EmailAddress = $_.PrimarySmtpAddress
#Other recipient properties here
}
}
} | Export-csv .\GroupmembersBeforeDel.csv -NoTypeInformation
#########################################
$groupowner = $distrotomovedetails.ManagedBy
$GroupOwnerCorrected = $groupowner.split('/')[-1]
$GroupOwnerCorrected.ToString()
$Managedby = Get-ADuser -Filter "displayName -eq '$GroupOwnerCorrected'"
$distrotomovedetails | fl
# Extract All Email Addresses for single group one per line so you can easily add back in EXO
$addresses = @()
Foreach ($mbx in $distrotomovedetails) {
Foreach ($address in $mbx.EmailAddresses) {
$obj = "" | Select-Object Identity,Alias,EmailAddress,RecipientType
$obj.Alias = $mbx.Alias
$obj.Identity = $mbx.Identity
$obj.RecipientType = $mbx.RecipientType
$obj.EmailAddress = $address.ToString().SubString(0)
$addresses += $obj
} } $addresses | Export-Csv .\SingleDistroGroupsmtpaddresses.csv -NoTypeInformation
$addresses
#Remove OnPremises Group
Remove-DistributionGroup -Identity $distrotomovedetails.Identity -Confirm:$false -Verbose
Start-Sleep 120
#Create On-Premises Contact
$ExternalEmailAddress = $distrotomovedetails.Alias + "@tenant.mail.onmicrosoft.com"
New-MailContact -DisplayName $distrotomovedetails.DisplayName -Alias $distrotomovedetails.Alias -ExternalEmailAddress $ExternalEmailAddress -OrganizationalUnit "OU=Contacts,OU=Exchange Accounts,DC=lge-mdr,DC=com"
Set-MailContact -Identity $distrotomovedetails.PrimarySmtpAddress -HiddenFromAddressListsEnabled $true
#Close Session with OnPremise Exchange
Get-PSSession | Remove-PSSession -Verbose
#Connect EXO
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -Credential $UserCredential
Write-Host -ForgroundColor Cyan "Running AAD Connect Sync"
#Remotely Run AAD Connect Delta Sync
$session = New-PSSession -ComputerName FQDNAADServer.com
Invoke-Command -Session $session -ScriptBlock {Import-Module -Name 'ADSync'}
Invoke-Command -Session $session -ScriptBlock {Start-ADSyncSyncCycle -PolicyType Delta}
Remove-PSSession $session
#Pause until AAD Connect Sync can run and Azure AD to catch up
Write-Host -ForgroundColor Green "Pausing for AAD Connect to run and then we check EXO for the group"
function Start-Sleep($seconds) {
$doneDT = (Get-Date).AddSeconds($seconds)
while($doneDT -gt (Get-Date)) {
$secondsLeft = $doneDT.Subtract((Get-Date)).TotalSeconds
$percent = ($seconds - $secondsLeft) / $seconds * 100
Write-Progress -Activity "Sleeping" -Status "Sleeping..." -SecondsRemaining $secondsLeft -PercentComplete $percent
[System.Threading.Thread]::Sleep(500)
}
Write-Progress -Activity "Sleeping" -Status "Sleeping..." -SecondsRemaining 0 -Completed
}
Start-Sleep 200
Write-host -ForegroundColor Cyan "Verifing the group is gone from Azure AD, command will proceed once group is not showing in EXO" $distrotomovedetails.PrimarySmtpAddress
while($GetDistroFinder -ne $null){
Write-Host -ForegroundColor Cyan "Checking EXO for the old synced Distro Group"
$GetDistroFinder = Get-DistributionGroup -Identity $distrotomovedetails.PrimarySmtpAddress
Start-Sleep 10
}
Write-Host -ForegroundColor Green "Group Appears to have been removed please verify on Azure AD"
Read-Host -Prompt "Hit Enter To Proceed"
############ Recreate Group in the cloud ###########################################################################################################################################
Write-Host -ForegroundColor Cyan "Recreating the group in EXO"
#Create the EXO Distro group
New-DistributionGroup -DisplayName $distrotomovedetails.DisplayName -Alias $distrotomovedetails.Alias -Name $distrotomovedetails.Name -MemberDepartRestriction $distrotomovedetails.MemberDepartRestriction -MemberJoinRestriction $distrotomovedetails.MemberJoinRestriction -PrimarySmtpAddress $distrotomovedetails.PrimarySmtpAddress -RequireSenderAuthenticationEnabled:$false -ManagedBy $Managedby.UserPrincipalName -Verbose
#Add additional SMTP and x500 addresses to the group.
Write-Host -ForegroundColor Green "Adding SMTP and x500 Addresses Back to" $distroprimarysmtp
$EmailAddressesToAdd = Import-Csv .\SingleDistroGroupsmtpaddresses.csv
$EmailAddressesToAdd | ForEach-Object {
$AliasOfGroup = $_.Alias
$AddressToAdd = $_.EmailAddress
$x500 = "x500:"+ $distrotomovedetails.LegacyExchangeDN
$GroupLookup = Get-DistributionGroup -Identity $AliasOfGroup
Set-DistributionGroup -Identity $GroupLookup.Identity -EmailAddresses @{Add=$AddressToAdd} -Verbose
}
#Add Group Members Back to Group
Write-Host -ForegroundColor Magenta "Adding Members Back to Group"
$GroupMembers = Import-Csv .\GroupmembersBeforeDel.csv
$GroupMembers | ForEach-Object {
$Distroprimarysmtp = $_.DistributionGroup
$MemberPrimarySMTP = $_.EmailAddress
Write-Host "Adding $memberprimarysmtp to $Distroprimarysmtp"
Add-DistributionGroupMember -Identity $Distroprimarysmtp -Member $MemberPrimarySMTP
}
#Confirm Group
Get-DistributionGroup $distroprimarysmtp | Select Alias,PrimarySmtpAddress,ManagedBy,IsDirsynced,WhenCreated | FT
}
- andydextrusNov 07, 2021Copper Contributor
Thank you for sharing this script Gregory Hall. I'm pretty much new to this as well.
In line with BrentPirolli's questions, please from where should this be run, Exchange on-prem or EXO? I shall also appreciate if you can please point out any customizations that need to be done to the script before running it in a new environment.- paul_sexstoneAug 03, 2023Copper Contributordid you get it working?
- andydextrusAug 16, 2023Copper Contributor
paul_sexstone Not at all Paul. I had to manually delete all the DLs from on-prem and then recreated them online eventually.
- Marine_RogMar 31, 2021Copper ContributorHi All,
I'm on Exchange Hybrid mode at the start of the Ex Migration.
We are starting to syncronize all DL On Premises to Online before migrate mailbox people to Online.
But we have a lot of request user to create new DL.
We try to create them directly on the Ex Online and we have doing a contact on the On Premise server.
But People who are still have mailbox on the On Premises server can't send email to this new DL created on the Online.
Can you help me please ?
Thanks in advance !- KevSH1967Jun 16, 2023Copper Contributor
Marine_Rog We're having the same issue. How were you able to resolve it?
- paul_sexstoneAug 03, 2023Copper Contributor
- BrentPirolliMar 30, 2021Copper Contributor
Gregory HallThis is pretty incredible! thanks for sharing. For a relative rookie at this, what of your script needs customized for my environment? I see a line referencing:
http://ExhangeServerFQDN.com/PowerShell/
which I'm guessing needs my URL... and
"@tenant.mail.onmicrosoft.com"
which I'm guessing I need to fill in with my tenant name in place of "tenant"... correct? Are there other areas?
Also... seeing this kicks off referencing:
$ListOfGroupsToMigrate = Import-csv .\GroupMigration.csv
Is there a specific script/format you are using to get that GroupMigration.csv or are you just pulling from something like:
$groups = get-adgroup -filter { (GroupCategory -eq 'Distribution') } -properties mail, name
$groupscsv = "C:\logs\GroupMigration.csv"
$groups | export-csv -Path $groupscsv
- spadge007Mar 17, 2021Copper Contributor