How to decommission Exchange Server 2010 after Office 365 Migration

Scenario

Organization has moved all their mailboxes to the Exchange Online from On-Premise Exchange 2010 server. MX Record is cutover to office365 (inbound and outbound mail flow is moved to office365). Active Directory Synchronization is being used for Syncing the users to Azure Active Directory using Azure AD Connect.

Requirement

Decommission Exchange 2010 server from the environment while keeping the Active Directory Synchronization through Azure AD Connect active / running.

Procedure

You may have used Hybrid Configuration Wizard (HCW) or Third party Tools to migrate the mailboxes to the cloud or you may have moved to higher version of exchange. Most of the steps given in this article will remain the same. However, This article will be based on one Exchange 2010 server with all exchange roles on it without DAG and without HCW configuration. You can use this article as a guidance and create a plan for decommissioning exchange server as per your organization requirements.

Important Note:
Please note Microsoft recommends not to fully decommission the last Exchange Server specially when Azure AD Connect is in use to sync the users to the cloud. If you still go ahead with Exchange server decommissioning, then most of the mail attributes needs to be managed via on-premise using Active Directory Schema Editor Snap-in or Third Party Tools or Powershell which is something not supported by Microsoft. (“MS recommendation: Remove all Exchange servers with the exception of the servers you will retain for user management and creation. Two servers should be sufficient for user management, although you could possibly get by with one server. In addition, there is no need to have a Database Availability Group or any other high availability options.”)  

Take Backup of mail Attributes from AD

Taking backup of important email attributes is not mandatory but its always a best practices to take the backup / export before the start of this activity. This can be used later for verifying the email attributes to make sure that mail attributes are populated correctly as per requirement.

Backup mail, mailNickName and proxyaddresses

Get-ADUser -Filter * -Properties proxyaddresses, mailNickName, Mail | Where { ($_.Enabled -eq $True) -and ($_.proxyaddresses -ne $null) } | Select-Object Name, Mail, mailNickName, @{ L = "ProxyAddresses"; E = {($_.ProxyAddresses | Where-Object {$_ -like "*smtp:*" }) -join ';'} } | Export-Csv -Path "c:\temp\UsersMailAttributes.csv" –NoTypeInformation

Backup X400 Addresses

Get-ADUser -Filter * -Properties proxyaddresses | Where { ($_.Enabled -eq $True) -and ($_.proxyaddresses -ne $null) } | Select-Object Name, @{ L = "ProxyAddresses"; E = {($_.ProxyAddresses | Where-Object {$_ -like "X400*" }) -join ';'} } | Export-Csv -Path "c:\temp\X400.csv" –NoTypeInformation

Backup X500 Addresses

Get-ADUser -Filter * -Properties proxyaddresses | Where { ($_.Enabled -eq $True) -and ($_.proxyaddresses -ne $null) } | Select-Object Name, @{ L = "ProxyAddresses"; E = {($_.ProxyAddresses | Where-Object {$_ -like "X500*" }) -join ';'} } | Export-Csv -Path "c:\temp\X500.csv" –NoTypeInformation

Other Commands for Reference (optional)

  • csvde -f c:\DLs.txt -r “(&(objectCategory=group)(proxyAddresses=*))”
  • csvde -f c:\Users.txt -r “(&(objectCategory=user)(proxyAddresses=*))”

Disable Azure AD Synchronization

Logon to the server where Azure AD Connect is installed and Disable the Azure AD Sync using below command.

Set-ADSyncScheduler -SyncCycleEnabled $false

Remove Service Connection Point (SCP)

Next, Remove the Service Connection Point (SCP) value on your Exchange Servers. SCP value is used for automatically configure outlook client. When you remove the Service connection point, the client will use the DNS method for autodiscover.

For Exchange 2010 Server:

Get-ClientAccessServer | fl AutoDiscoverServiceInternalUri
Get-ClientAccessServer | Set-ClientAccessServer -AutoDiscoverServiceInternalUri $Null

Exchange 2016 Server or later:

Get-ClientAccessService | Set-ClientAccessService -AutoDiscoverServiceInternalUri $Null

If you are unable to remove the Service Connection Point using Powershell. You can open ADSIEdit and delete the Service connection Point manually.

Open ADSIEdit -> Configuration Partition -> Services -> Microsoft Exchange -> CN = <Exchange Organization> -> Administrative Groups -> Servers -> <Exchange Server Name> ->Protocols -> Autodiscover-> Under this folder you will see serviceConnectionPoint. Delete this manually. However, I will prefer the Powershell command option as its easier and less complex than using ADSIEdit.

Delete offline Address Books (OAB’s)

you can use Powershell to remove the offline Address Books (OAB’s) or manually using the Exchange management console (EMC). Please find both the methods below and use the one preferable to you.

Using Powershell

Get-OfflineAddressBook
Get-OfflineAddressBook | Remove-OfflineAddressBook
Get-OfflineAddressBook

Using GUI Method

Open Exchange Management Console -> Organization Configuration -> Mailbox -> offline Address Book -> Select All the Offline Address Books and Right click Select Remove.

Migration of Public Folders

Run Get-OrganizationConfig |fl PublicFoldersEnabled and ensure that it is not set to remote. If it is set to remote and you want to continue to access the public folders, you would need to migrate them to Exchange Online. If you have already migrated Public Folders to Exchange Online, Please proceed to the next section for Delete Public Folders.

Delete Public Folders

Before deleting the Public Folders, Please open the <strong>Exchange Management Console -> Toolbox -> Open Public Folder Management Console.</strong> Please check the existence of Public Folders on this console.

Use below command to delete all public folders.

Get-PublicFolder -Server ExchangeServerHostName “\” -Recurse -ResultSize:Unlimited | Remove-PublicFolder -Server ExchangeServerHostName -Recurse -ErrorAction:SilentlyContinue

Once all the Public Folders are deleted. Please open the Public folder management console again to verify the deletion (as shown in below screenshot).

Delete Public Folder Database

Now, you can Delete the Public Folder Database from the Exchange Management console (However, if you receive an error message as shown below, please follow the given steps to fix the error).

Error:
The public folder database “Public Folder Database” contains folder replicas. Before deleting the public folder database, remove the folders or move the replicas to another public folder database. For detailed instructions about how to remove a public folder database, see http://go.microsoft.com/fwlink/?linkid=81409&clcid=0x409.

You can check the replicas using below command

Get-PublicFolder -Recurse | ft name,parentpath,replicas

You can see the folder replicas are still there for the Public Folder Database. To get around this issue, I have dismounted the Public folder database, moved the public folder database folder contents (which includes database and log files, if your log file’s location is different than the database location, go to the log file folder and move its contents as well) to a new directory and the mount the public folder database again and Delete it. I will show you how I fixed this error and some alternative methods to fix it. If you want jump straight to Alternative method which i have not tested myself Please check: Alternate Fix for Replica Error in next section.

a) Dismount the Public Folder Database(s)

Dismount-Database -Identity PublicFolderDatabaseName

b) Note down the Public Folder database and log file paths. You can also check this information by right clicking the Public Folder Database and click properties -> General Tab.

Get-PublicFolderDatabase | fl name, *Path*

c) Move the Contents of EdbFilepath and LogFolderPath Folder to another new Folder. I created a new folder movePFcontents in I:\ drive. You can create the folder on any drive or location provided you have enough free space to move the Public Folder Database and Log Folder Contents. You can also manually move the data using GUI tools, I have used move command to move the contents

d) Mount the Public Folder Database

 Mount-Database -identity publicfolderdatabasename

You can now try to delete the Public Folder database at this stage. However, If you receive below error message then please follow further guidance to fix the issue.

The public folder database ‘PublicFolderDatabaseName’ cannot be deleted.

Error:
Public folder database “PublicFolderDatabaseName” is the default public folder database for the following mailbox database(s):

Mailboxdatabasename

. Before deleting the public folder database, assign a new default public folder database to the mailbox database(s).

Error Message when trying to delete the public folder database

Screenshot

Solution

First we need to check the default public folder associated for each mailbox database. Run the command Get-MailboxDatabase | ft name, publicfolderdatabase. You can see that mailbox database(s) are having association with public folder database. We need to remove this association to fix this issue so that that mailbox database will not be able to use the public folder DB.

Get-MailboxDatabase | ft name, publicfolderdatabase

Deleting this association by using Set-Mailboxdatabase command didn’t work in my case, so I have used the ADSI Edit to delete the associations manually.

Open ADSI Editor -> Configuration Partition -> CN=Services -> CN=Microsoft Exchange -> CN=(<your organization name>) -> CN=Administrative Groups -> CN=Exchange Administrative Group (<group name>) -> CN=Databases.

Right click on each mailbox database for which you noted the association with public folder databases and click properties -> Attributes Editor. Search for msExchHomePublicMDB attribute and clear the value.

Repeat for all other Mailbox databases and then check the association of mailbox database with public folder again to make sure that you have removed all association(s). Use the same command which was used earlier. Get-MailboxDatabase | ft name, publicfolderdatabase

Get-MailboxDatabase | ft name, publicfolderdatabase

Now, try to delete the Public Folder Databases. You can see that the Public folder database is now removed.

Get-PublicFolderDatabase | Remove-PublicFolderDatabase

Alternate Fix for Replica Error

Go back to Delete Public Folder Database Section

If you have received a pop-up message: (Error: The public folder database “Public Folder Database” contains folder replicas. Before deleting the public folder database, remove the folders or move the replicas to another public folder database. For detailed instructions about how to remove a public folder database, see http://go.microsoft.com/fwlink/?linkid=81409&clcid=0x409), you can use below commands to fix it as well. But, I have not tested the below method / commands myself so i am not sure if this will work or not. But, if you are able to try the below method and if it works fine. Please let me know in the comments section.

Set-OrganizationConfig -PublicFolderMigrationComplete $True
Remove-PublicFolderDatabase "Public Folder Database" -RemoveLastAllowed

Disable and Delete Mailboxes

Next task is to Disable All Mailboxes. Once you disable a user mailbox using Exchange Management console or Exchange Management Shell, mail related attributes are removed from On-Premise Active Directory for that user. Therefore, we need to convert the disabled user mailbox to Mail User (how to convert this is shown in next section) so that we can re-populate the mail attributes for the user. It is important that you make sure that Azure AD connect sync is stopped by using Set-ADSyncScheduler -SyncCycleEnabled $false command. (Note: If Azure AD Sync is not paused and you disable a mailbox which removes the mail related attributes from On-Premise Active Directory user and then Once the AD Sync runs it will convert the users email address to onmicrosoft.com addresses on office365)

Below mail attributes are removed from user when you disable a user mailbox

  • EmailAddress
  • legacyExchangeDN
  • mailNickname
  • mail  
  • msExchHomeServerName
  • textEncodedORAddress
  • showInAddressBook
  • proxyAddresses
  • msExchUserAccountControl
  • msExchVersion
  • msExchMailboxSecurityDescriptor
  • msExchRBACPolicyLink
  • msExchPoliciesIncluded
  • homeMDB
  • homeMTA 
  • mDBUseDefaults        

Disable Mailbox and Convert User Mailbox to Mail User

For One User

  • Launch Powershell on the Azure AD Connect Server
  • Import-Module ADSync
  • <a href="https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sync-feature-scheduler" target="_blank" rel="noreferrer noopener"><span style="text-decoration: underline;">Set-ADSyncScheduler</span></a> -SyncCycleEnabled $false

I have divided this section in two parts. If you are testing with One user, you can use “For One User” Steps and if you are converting all users mailbox to mail user then you can use “For All Users” Section.

Important Note:
Please take backup of user email aliases before disabling user mailbox because converting a user to a mail user will not restore the aliases back, only primary SMTP address is restored after converting a user to mail user. Once a user is converted to mail user, restore / add user aliases by going to Active Directory -> User Account Properties -> Attribute editor -> proxyAddresses -> type the aliases as smtp:<user email alias>. For Example: smtp:jmakhija@techpress.net. Use Uppercase SMTP: for Primary SMTP email address and lowercase smtp: for all user email aliases.
  • Open <strong>Exchange Management Console -> Recipient configuration -> Mailbox -> Select User Mailbox -> Right Click on it and select disable.</strong>
  • If you are using Powershell (Exchange management shell), you can use the command <strong><a rel="noreferrer noopener" href="https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/disable-mailbox?view=exchange-ps" target="_blank"><span style="text-decoration: underline;">Disable-Mailbox</span></a> -Identity <user's unique Identifier e.g. Name, Alias etc></strong>

If you disable a user mailbox and then you check the Disconnected mailbox folder on exchange management console, you may not see the mailbox immediately appear in Disconnected Mailbox folder. If you want to force it to appear in this folder. Use the command <a href="https://docs.microsoft.com/en-us/powershell/module/exchange/mailbox-databases-and-servers/get-mailboxdatabase?view=exchange-ps" target="_blank" rel="noreferrer noopener"><span style="text-decoration: underline;">Get-Mailboxdatabase</span></a> | <a href="https://docs.microsoft.com/en-us/powershell/module/exchange/mailbox-databases-and-servers/clean-mailboxdatabase?view=exchange-ps" target="_blank" rel="noreferrer noopener"><span style="text-decoration: underline;">Clean-mailboxdatabase</span></a>, Go back to EMC and refresh the Disconnected Mailbox Folder.

c) Convert User Mailbox to Mail User

Before you convert User Mailbox to Mail User, you need to know the externalEmailAddress value. You can provide a parameter value explicitly e.g. jatin.makhija@techpress.net or you can use userprincipalname or samAccountName as a reference to populate the value. I have used userprincipalname in the below command because my exchange users Primary SMTP Address matches with the userprincipalname in Active Directory.

Once you have identified the externalEmailAddress value, you can run below command against one user to convert disabled User to Mail User.

Important Note:
Please note that I am assuming that your Active Directory UPN matches the Primary SMTP Address, if not then use a script to match UPN to primary SMTP address (pSMTP). if you do not want to match UPN to pSMTP then you can use a samAccountname parameter instead of userprincipalname or copy externalmailaddress for each user in csv and modify the below command according to your requirements.
$userlist = get-user -Identity "Username"
$userlist | foreach {Enable-MailUser $_ -externalEmailAddress “$($_.userprincipalname)” }

If you want to use samAccountName instead of userprincipalname

$userlist = get-user -Identity "Username"
$userlist | foreach { Enable-MailUser $_ -externalEmailAddress “$($_.samaccountname)@DOMAIN.COM” }

d) Now the user has been converted to Mail User, you can check in on-premise Active Directory, Users email attributes are added / updated again. Below email attributes are added / updated to the on-premise user:

1. EmailAddress
2. InternetEncoding
3. legacyExchangeDN
4. mail
5. mailNickname
6. msExchPoliciesIncluded
7. msExchRecipientDisplayType
8. msExchRecipientTypeDetails
9. msExchVersion
10. proxyAddresses
11. showInAddressBook
12. targetAddress
13. textEncodedORAddress

e) Resume AD Connect sync

Set-ADSyncScheduler -SyncCycleEnabled $true

f)Test email Flow for this mail user.

g) Purge the disabled / disconnected user mailbox

Check the mailboxes which are in disconnected state or in disabled state. Note Down the mailbox guid of the user which you want to purge from database.

Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {$_.DisconnectDate –notlike ‘’}} | select displayname, mailboxguid, database

If you want to purge a specific disconnected / disabled mailbox, then use the mailboxguid noted above and replace it in below command. Below command will capture the disconnected user matching the mailbox guid in $mailboxes variable.

$mailboxes = Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {($_.DisconnectDate –notlike ‘’) -and ($_.Mailboxguid -eq '87b867e5-b0ol-4jj2-b0d9-13a3n78933e49')}} | select displayname, mailboxguid, database

Purge the mailbox which is captured / stored in $mailboxes variable.

$mailboxes | ForEach { Remove-Mailbox -Database $_.Database -StoreMailboxIdentity $_.MailboxGuid -confirm:$false }

Verify / confirm that the disconnected or disabled mailbox have been purged.

Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {$_.DisconnectDate –notlike ‘’}} | select displayname, mailboxguid, database

For All Users

When you want to disable all users at once and convert it to mail users, you can follow below procedure. Most of the process will be same as applied for one user. The only difference is that the commands will run against all Mailboxes.

a) Pause Azure AD Sync (ignore if its already done)

  • Launch Powershell on the Azure AD Connect Server
  • Import-Module ADSync
  • Set-ADSyncScheduler -SyncCycleEnabled $false
Important Note:
Please take backup of user email aliases before disabling user mailbox because converting a user to a mail user will not restore the aliases back, only primary SMTP address is restored after converting a user to mail user. Once a user is converted to mail user, restore / add user aliases by going to Active Directory -> User Account Properties -> Attribute editor -> proxyAddresses -> type the aliases as smtp:<user email alias>. For Example: smtp:jmakhija@techpress.net. Use Uppercase SMTP: for Primary SMTP email address and lowercase smtp: for all user email aliases.

b) Disable All mailboxes

c) Once the Mailboxes are disabled, convert each disabled user to mail User using below commands. (Important Note: Please note that I am assuming that your Active Directory UPN matches the Primary SMTP Address, if not then use this script to match UPN to pSMTPif you do not want to match UPN to pSMTP then you can update the below command to use samAccountname instead of userprincipalname or copy externalmailaddress for each user in csv and modify the below command according to your requirements).

$userlist = Get-user -Filter { RecipientType -eq “user” } 
$userlist | foreach {Enable-MailUser $_ -externalEmailAddress “$($_.userprincipalname)” }

If you want to use samAccountName instead of userprincipalname

$userlist = Get-user -Filter { RecipientType -eq “user” }
$userlist | foreach { Enable-MailUser $_ -externalEmailAddress “$($_.samaccountname)@DOMAIN.COM” }

d) Resume AD Connect sync

Set-ADSyncScheduler -SyncCycleEnabled $true

e) Test email Flow for few random users to confirm the mail flow.

f) Now, Check all the disconnected / disabled mailboxes

Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {$_.DisconnectDate –notlike ‘’}} | select displayname, mailboxguid, database

g) Run below command to capture all the disconnected mailboxes in a variable:

$mailboxes = Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {$_.DisconnectDate –notlike ‘’}} | select displayname, mailboxguid, database

h) Purge all mailboxes

$mailboxes | ForEach { Remove-Mailbox -Database $_.Database -StoreMailboxIdentity $_.MailboxGuid -confirm:$false }

i) Verify if all the mailboxes are now purged:

Get-ExchangeServer | Where-Object {$_.IsMailboxServer –eq $true} | ForEach-Object { Get-MailboxStatistics –Server $_.Name | Where-Object {$_.DisconnectDate –notlike ‘’}} | select displayname, mailboxguid, database

Disable Arbitration mailboxes

a) Get a list of Arbitration / system mailboxes.

Get-Mailbox -Arbitration

b) Disable the Arbitration Mailboxes using below command:

Get-mailbox -Arbitration | Disable-Mailbox -Arbitration -DisableLastArbitrationMailboxAllowed

c) Once arbitration mailboxes are disabled. Make sure you do not see any Arbitration Mailboxes when you run Get-Mailbox -Arbitration command:

Get-Mailbox -Arbitration

Delete SystemMailbox objects from Active Directory

Open Active Directory Users and Computers-> Search for System Mailbox accounts and right click on them -> Select Delete

Remove Send and Receive Connectors

You can use Exchange Management Console (EMC) or Powershell to remove the send connectors. I have used Powershell command as shown below.

Remove Send Connector

Get-SendConnector | Remove-SendConnector

Remove Receive Connector

Get-ReceiveConnector | Remove-ReceiveConnector

Delete Mailbox Import Requests

Run below command to check if there are mailbox import requests in the queue.

Get-MailboxImportRequest

Remove MailboxImport Requests:

Get-MailboxImportRequest | Remove-MailboxImportRequest

Make sure all Mailbox Import Requests are deleted:

Get-MailboxImportRequest

Uninstall Microsoft Exchange 2010 from the server

Before starting this process, Please make sure Exchange Management Shell (EMS) window is closed, Else you will receive an error about Powershell has open files.

  1. Go to Start -> Run -> Appwiz.cpl
  2. Select Microsoft Exchange Server 2010 -> Right click -> Uninstall

Test Email Flow

  • Check Inbound / outbound email flow
  • Check Azure AD Sync Health Status
  • Login on office365 admin portal to check the users accounts and make sure there are no issues / errors.

Uninstall Other Softwares from Exchange server

Uninstall other software(s) from exchange server like Anti-Virus, Backup Software, Veritas backup exec agent, or any other third party tools to cleanup the meta-data and release the licenses (if any).

Disjoin Exchange Sever from domain

Now, you can remove the server from domain. Please make sure to create local admin account on the server so that you can login on the server if required. Delete the meta-data of the Exchange Server(s) like computer account in AD etc.

Power down Exchange Server

Now, you can Power down the Exchange server and remove it from monitoring systems if it was added to monitoring systems.

Monitoring and Deletion of Exchange Server from the disk

You can monitor the server after power down and then if its a virtual server, delete it from disk if there are no issues reported.

Update Documentation

Update the documentation related to Exchange Server where applicable.

External Reference / Links:

Exchange 2010 end of support roadmap

How and when to decommission your on-premises Exchange servers in a hybrid deployment

Subscribe to Stay Connected

Thank you for visiting TechPress 👍. When you subscribe to the blog, email notification ✉ will be sent to you when a new blog post is published. You can unsubscribe at any time.

guest
37 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments