moving on-prem users to Entra
If you're an organisation with a Hybrid identity setup, you may eventually want to move some of those on-prem users into cloud-only accounts. Such users might be legacy shared mailbox accounts, external contractors, or just accounts kept for archival.
Pro tip: Shared mailboxes don't need a 365 license (if their archives are < 50GB), use this trick to save on licenses.
When moving users, there's a few pitfalls and cleanup tasks to be run to stop Entra Connect from erroring out.
To start, assign all of the targetted accounts with a license. This won't be permanent but you should have licenses spare to avoid losing archives.
From what I understand the archives should be kept for up to 30 days even if they are outside of license limits, but I always assign licenses to be safe.
I'm assigning Office E3, your SKU number might differ.
param($UserId)
Connect-MgGraph -Scopes User.ReadWrite.All, Organization.Read.All
$officee3 = Get-MgSubscribedSku -All | Where-Object SkuPartNumber -eq 'ENTERPRISEPACK'
Set-MgUserLicense -UserId $UserId -AddLicenses @{ SkuId = $officee3.SkuId } -RemoveLicenses @()
Next, stop your on-premise users from syncing. This will "delete" them, which is intentional. I use a specific OU which is excluded from Entra Connect for this purpose. Run a sync or wait for the sync to complete.
Now the mailboxes should have disappeared from Entra/Exchange. You can go to the main admin center > Users > Deleted Users to restore them.
We now need to clean up the onPremisesImmutableId
property:
Connect-MgGraph -Scopes User.ReadWrite -NoWelcome
$upn = "<user UPN>"
$user = Get-MgUser -UserId $upn -Property OnPremisesImmutableId, Id | Select-Object Id, OnPremisesImmutableId
Write-Output $user
$userId = $user.Id
$body = @{
onPremisesImmutableId = $null
}
Invoke-MgGraphRequest -Method PATCH -Uri "https://graph.microsoft.com/v1.0/users/$userId" -Body $body
This will break the on-premise link. Be sure you're operating on the right accounts.
Wait for the Exchange mailboxes to get assigned, then verify they are all set to SharedMailbox mode:
$upnList | ForEach-Object { Get-Mailbox $_ } | fl PrimarySmtpAddress, RecipientTypeDetails
That's it, you can now clean up the licenses and disable the accounts (if relevant):
$params = @{
accountEnabled = $false
}
$upnList | ForEach-Object {
$archiveStats = Get-ExoMailboxStatistics -Archive $_ -ErrorAction SilentlyContinue
if (($null -ne $archiveStats) -and ($archiveStats.TotalItemSize.Value.ToBytes() -gt 40GB)) {
Write-Error "User $_ has mailbox too large to stay unlicensed"
exit 1
}
if ($null -eq $archiveStats) {
Write-Error "Couldn't find archive for mailbox $UserId"
exit 1
}
# Remove our E3 license and Business Premium if applied
$license = Get-MgSubscribedSku -All | Where-Object SkuPartNumber -eq 'ENTERPRISEPACK'
Set-MgUserLicense -UserId $_ -AddLicenses @() -RemoveLicenses @($license.SkuId) -ErrorAction SilentlyContinue
$license = Get-MgSubscribedSku -All | Where-Object SkuPartNumber -eq 'SPB'
Set-MgUserLicense -UserId $_ -AddLicenses @() -RemoveLicenses @($license.SkuId) -ErrorAction SilentlyContinue
Write-Host "Removed licenses for $_"
Update-MgUser -UserId $_ -BodyParameter $params
}