|
| 1 | +# Clear-OnPremExchangeAttributes |
| 2 | + |
| 3 | +## Overview |
| 4 | +Removes on-premises Exchange attributes from Active Directory user accounts to enable cloud mailbox provisioning in Exchange Online. This script is essential when decommissioning on-premises Exchange or migrating to a cloud-only Exchange Online environment without hybrid configuration. |
| 5 | + |
| 6 | +## Features |
| 7 | +- **Pre-execution backup** of all Exchange attributes to CSV with base64 encoding for binary data |
| 8 | +- **Comprehensive attribute removal** including msExchMailboxGuid (primary blocker) and 18+ other Exchange attributes |
| 9 | +- **Rollback capability** using backup data with `-RestoreFromBackup` parameter |
| 10 | +- **Flexible targeting** - single user, OU-based, or CSV bulk import |
| 11 | +- **WhatIf support** for safe testing before execution |
| 12 | +- **Detailed logging** with timestamped status messages and color-coded output |
| 13 | +- **Automatic validation** checks before and after cleanup |
| 14 | +- **Summary reports** with execution statistics and next steps |
| 15 | + |
| 16 | +## Prerequisites |
| 17 | +- **Active Directory PowerShell module** (RSAT tools) |
| 18 | +- **Domain Administrator or Account Operator permissions** |
| 19 | +- **PowerShell 5.1 or later** |
| 20 | +- **Network connectivity** to Active Directory domain controllers |
| 21 | + |
| 22 | +## Parameters |
| 23 | + |
| 24 | +### Required Parameters (choose one mode) |
| 25 | +- **Identity**: The SamAccountName, UserPrincipalName, or DistinguishedName of a single user to process |
| 26 | +- **SearchBase**: Active Directory OU to search for users (e.g., "OU=Users,OU=ToMigrate,DC=contoso,DC=com") |
| 27 | +- **InputFile**: Path to CSV file with users (must contain 'Identity' column) |
| 28 | + |
| 29 | +### Optional Parameters |
| 30 | +- **OutputDirectory**: Directory for backups and reports (Default: `C:\Reports\ExchangeCleanup`) |
| 31 | +- **AttributesToRemove**: Specific Exchange attributes to remove (defaults to standard blocking attributes) |
| 32 | +- **BackupOnly**: Only creates backup without removing attributes (useful for assessment) |
| 33 | +- **RestoreFromBackup**: Path to backup CSV file for rollback operations |
| 34 | +- **WhatIf**: Shows what would happen without making changes |
| 35 | +- **Force**: Bypasses confirmation prompts (use with caution) |
| 36 | +- **ListAttributes**: Lists all Exchange-related attributes and exits |
| 37 | + |
| 38 | +## Usage Examples |
| 39 | + |
| 40 | +### Example 1: Test Single User (Recommended First Step) |
| 41 | +```powershell |
| 42 | +.\Clear-OnPremExchangeAttributes.ps1 -Identity "jsmith" -WhatIf |
| 43 | +``` |
| 44 | +Tests removal of Exchange attributes without making changes. Review the attributes that would be removed. |
| 45 | + |
| 46 | +### Example 2: Clean Single User |
| 47 | +```powershell |
| 48 | +.\Clear-OnPremExchangeAttributes.ps1 -Identity "jsmith" |
| 49 | +``` |
| 50 | +Backs up and removes Exchange attributes for user jsmith. Requires typing `PROCEED` to confirm. |
| 51 | + |
| 52 | +### Example 3: Assessment Only (Backup Without Removal) |
| 53 | +```powershell |
| 54 | +.\Clear-OnPremExchangeAttributes.ps1 -Identity "jsmith" -BackupOnly |
| 55 | +``` |
| 56 | +Creates backup of Exchange attributes without removing them. Useful for auditing what attributes exist. |
| 57 | + |
| 58 | +### Example 4: Bulk Processing from CSV |
| 59 | +```powershell |
| 60 | +# Create CSV with user identities |
| 61 | +$users = @('jsmith', 'mjones', 'bwilson') |
| 62 | +$users | ForEach-Object { [PSCustomObject]@{Identity=$_} } | Export-Csv "C:\temp\users.csv" -NoTypeInformation |
| 63 | +
|
| 64 | +# Process all users |
| 65 | +.\Clear-OnPremExchangeAttributes.ps1 -InputFile "C:\temp\users.csv" |
| 66 | +``` |
| 67 | +Processes multiple users from CSV file. Type `PROCEED` when prompted to execute. |
| 68 | + |
| 69 | +### Example 5: Process Entire OU |
| 70 | +```powershell |
| 71 | +.\Clear-OnPremExchangeAttributes.ps1 -SearchBase "OU=ToMigrate,OU=Users,DC=contoso,DC=com" |
| 72 | +``` |
| 73 | +Backs up and removes Exchange attributes for all users in specified OU. |
| 74 | + |
| 75 | +### Example 6: Force Execution (No Prompts) |
| 76 | +```powershell |
| 77 | +.\Clear-OnPremExchangeAttributes.ps1 -Identity "jsmith" -Force |
| 78 | +``` |
| 79 | +Bypasses confirmation prompt. Use with caution in production. |
| 80 | + |
| 81 | +### Example 7: Restore from Backup (Rollback) |
| 82 | +```powershell |
| 83 | +.\Clear-OnPremExchangeAttributes.ps1 -RestoreFromBackup "C:\Reports\ExchangeCleanup\ExchangeAttributes_Backup_20260202_143052.csv" |
| 84 | +``` |
| 85 | +Restores Exchange attributes from previous backup. Requires typing `RESTORE` to confirm. |
| 86 | + |
| 87 | +### Example 8: List Available Attributes |
| 88 | +```powershell |
| 89 | +.\Clear-OnPremExchangeAttributes.ps1 -ListAttributes |
| 90 | +``` |
| 91 | +Displays all Exchange attributes that can be removed (default and extended lists). |
| 92 | + |
| 93 | +## Output |
| 94 | + |
| 95 | +### Console Output |
| 96 | +The script provides real-time color-coded status messages: |
| 97 | +- **Cyan** - Informational messages and headers |
| 98 | +- **Green** - Success messages with ✅ checkmark |
| 99 | +- **Yellow** - Warnings with ⚠️ symbol |
| 100 | +- **Red** - Errors with ❌ symbol |
| 101 | + |
| 102 | +### Output File Locations |
| 103 | +Default output directory: `C:\Reports\ExchangeCleanup\` |
| 104 | + |
| 105 | +Generated files follow timestamp pattern: `{Type}_{YYYYMMDD_HHmmss}.{ext}` |
| 106 | + |
| 107 | +#### 1. Backup File (CSV) |
| 108 | +**Pattern**: `ExchangeAttributes_Backup_YYYYMMDD_HHmmss.csv` |
| 109 | + |
| 110 | +**Example**: `ExchangeAttributes_Backup_20260202_143052.csv` |
| 111 | + |
| 112 | +Contains complete backup of all Exchange attributes for processed users including: |
| 113 | +- Standard user properties (SamAccountName, UPN, DN, DisplayName, Enabled) |
| 114 | +- All Exchange attributes (msExchMailboxGuid, legacyExchangeDN, mailNickname, etc.) |
| 115 | +- Binary data encoded in base64 format |
| 116 | +- Backup timestamp |
| 117 | + |
| 118 | +#### 2. Results File (CSV) |
| 119 | +**Pattern**: `ExchangeCleanup_Results_YYYYMMDD_HHmmss.csv` |
| 120 | + |
| 121 | +**Example**: `ExchangeCleanup_Results_20260202_143052.csv` |
| 122 | + |
| 123 | +Contains detailed results for each user: |
| 124 | +- `User`: SamAccountName |
| 125 | +- `RemovedCount`: Number of attributes successfully removed |
| 126 | +- `RemovedAttributes`: List of removed attribute names |
| 127 | +- `FailedAttributes`: List of attributes that failed to remove |
| 128 | +- `SkippedAttributes`: Attributes with no values |
| 129 | +- `Success`: Boolean indicating if operation succeeded |
| 130 | + |
| 131 | +#### 3. Summary Report (TXT) |
| 132 | +**Pattern**: `ExchangeCleanup_Summary_YYYYMMDD_HHmmss.txt` |
| 133 | + |
| 134 | +**Example**: `ExchangeCleanup_Summary_20260202_143052.txt` |
| 135 | + |
| 136 | +Comprehensive summary including: |
| 137 | +- Operation statistics (total processed, successful, errors, skipped) |
| 138 | +- File locations for backup and results |
| 139 | +- Execution time and duration |
| 140 | +- Error details if any occurred |
| 141 | +- Next steps for completing migration |
| 142 | + |
| 143 | +## Exchange Attributes Removed |
| 144 | + |
| 145 | +### Default Attributes (Primary Blockers) |
| 146 | +These attributes prevent cloud mailbox provisioning: |
| 147 | + |
| 148 | +- **msExchMailboxGuid** - Primary blocker, must be removed |
| 149 | +- **msExchArchiveGUID** - Archive mailbox identifier |
| 150 | +- **msExchRemoteRecipientType** - Remote recipient type flags |
| 151 | +- **msExchRecipientDisplayType** - Display type (1073741824 = user mailbox) |
| 152 | +- **msExchRecipientTypeDetails** - Detailed recipient type |
| 153 | +- **msExchUserCulture** - User locale settings |
| 154 | +- **msExchVersion** - Exchange schema version |
| 155 | +- **msExchMailboxSecurityDescriptor** - Mailbox permissions |
| 156 | +- **msExchMasterAccountSid** - Master account SID |
| 157 | +- **msExchPoliciesExcluded** - Policy exclusions |
| 158 | +- **msExchRecipientSoftDeletedStatus** - Soft delete status |
| 159 | +- **msExchUserAccountControl** - Account control flags |
| 160 | +- **msExchWhenMailboxCreated** - Mailbox creation timestamp |
| 161 | +- **mailNickname** - Exchange alias |
| 162 | +- **legacyExchangeDN** - Legacy distinguished name |
| 163 | +- **targetAddress** - Routing address |
| 164 | +- **msExchHomeServerName** - Home server path |
| 165 | +- **homeMDB** - Mailbox database location |
| 166 | +- **msExchMailboxTemplateLink** - Mailbox template reference |
| 167 | + |
| 168 | +### Extended Attributes (Comprehensive Cleanup) |
| 169 | +Additional attributes removed with `-AttributesToRemove` parameter: |
| 170 | + |
| 171 | +- msExchAddressBookFlags, msExchArchiveDatabaseLink, msExchArchiveName |
| 172 | +- msExchArchiveQuota, msExchArchiveWarnQuota, msExchBypassAudit |
| 173 | +- msExchBypassModerationLink, msExchDelegateListLink, msExchELCMailboxFlags |
| 174 | +- msExchHideFromAddressLists, msExchMailboxAuditEnable, msExchMailboxFolderSet |
| 175 | +- msExchMobileMailboxFlags, msExchProvisioningFlags, msExchRBACPolicyLink |
| 176 | +- msExchRecipientLimit, msExchRetentionComment, msExchRetentionURL |
| 177 | +- msExchSafeSendersHash, msExchTextMessagingState, msExchUMDtmfMap |
| 178 | + |
| 179 | +## Common Issues & Troubleshooting |
| 180 | + |
| 181 | +### Issue: "Active Directory PowerShell module is not installed" |
| 182 | +**Solution**: Install RSAT tools: |
| 183 | +```powershell |
| 184 | +# Windows 10/11 |
| 185 | +Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 |
| 186 | +
|
| 187 | +# Windows Server |
| 188 | +Install-WindowsFeature RSAT-AD-PowerShell |
| 189 | +``` |
| 190 | + |
| 191 | +### Issue: "Cannot connect to Active Directory" |
| 192 | +**Solution**: |
| 193 | +- Ensure you're running from domain-joined machine |
| 194 | +- Verify network connectivity to domain controller |
| 195 | +- Check if you have appropriate permissions |
| 196 | + |
| 197 | +### Issue: "No write permission to output directory" |
| 198 | +**Solution**: |
| 199 | +```powershell |
| 200 | +# Run with different output directory |
| 201 | +.\Clear-OnPremExchangeAttributes.ps1 -Identity "jsmith" -OutputDirectory "C:\temp\ExchangeCleanup" |
| 202 | +``` |
| 203 | + |
| 204 | +### Issue: "Could not find user: username" |
| 205 | +**Solution**: |
| 206 | +- Verify user exists in Active Directory |
| 207 | +- Check spelling of username |
| 208 | +- Try using UserPrincipalName or DistinguishedName instead |
| 209 | + |
| 210 | +### Issue: "Successfully Cleaned: 0" with no errors |
| 211 | +**Cause**: Attributes may not have values or were already removed |
| 212 | + |
| 213 | +**Solution**: Check backup CSV to see if attributes existed: |
| 214 | +```powershell |
| 215 | +Import-Csv "C:\Reports\ExchangeCleanup\ExchangeAttributes_Backup_*.csv" | |
| 216 | + Select-Object SamAccountName, msExchMailboxGuid, mailNickname, legacyExchangeDN | |
| 217 | + Format-List |
| 218 | +``` |
| 219 | + |
| 220 | +### Issue: Mailbox still won't provision after cleanup |
| 221 | +**Possible Causes**: |
| 222 | +1. Azure AD Connect hasn't synced changes yet |
| 223 | +2. User still has mailbox license assigned before attributes were cleared |
| 224 | +3. Deleted mailbox still in soft-deleted state in Exchange Online |
| 225 | + |
| 226 | +**Solution**: |
| 227 | +```powershell |
| 228 | +# 1. Force Azure AD Connect sync |
| 229 | +Start-ADSyncSyncCycle -PolicyType Delta |
| 230 | +
|
| 231 | +# 2. Wait 15-30 minutes, then remove and reassign license |
| 232 | +
|
| 233 | +# 3. Check for soft-deleted mailboxes in Exchange Online |
| 234 | +Connect-ExchangeOnline |
| 235 | +Get-Mailbox -SoftDeletedMailbox -Identity "user@domain.com" |
| 236 | +``` |
| 237 | + |
| 238 | +## Rollback Procedure |
| 239 | + |
| 240 | +If mailbox provisioning fails or you need to restore original state: |
| 241 | + |
| 242 | +```powershell |
| 243 | +# Restore from backup |
| 244 | +.\Clear-OnPremExchangeAttributes.ps1 -RestoreFromBackup "C:\Reports\ExchangeCleanup\ExchangeAttributes_Backup_20260202_143052.csv" |
| 245 | +
|
| 246 | +# Type: RESTORE |
| 247 | +# Wait for completion |
| 248 | +
|
| 249 | +# Force Azure AD Connect sync |
| 250 | +Start-ADSyncSyncCycle -PolicyType Delta |
| 251 | +``` |
| 252 | + |
| 253 | +## Post-Cleanup Steps |
| 254 | + |
| 255 | +### 1. Review Backup and Results |
| 256 | +```powershell |
| 257 | +# Check what was removed |
| 258 | +Import-Csv "C:\Reports\ExchangeCleanup\ExchangeCleanup_Results_*.csv" | |
| 259 | + Where-Object { $_.RemovedCount -gt 0 } | |
| 260 | + Format-Table User, RemovedCount, Success -AutoSize |
| 261 | +``` |
| 262 | + |
| 263 | +### 2. Force Azure AD Connect Sync (Hybrid Environments) |
| 264 | +```powershell |
| 265 | +# On Azure AD Connect server |
| 266 | +Start-ADSyncSyncCycle -PolicyType Delta |
| 267 | +``` |
| 268 | + |
| 269 | +### 3. Wait for Replication |
| 270 | +Allow 15-30 minutes for changes to replicate to Azure AD. |
| 271 | + |
| 272 | +### 4. Assign Exchange Online Licenses |
| 273 | +```powershell |
| 274 | +Connect-MgGraph -Scopes "User.ReadWrite.All" |
| 275 | +
|
| 276 | +# Assign license (example) |
| 277 | +Set-MgUserLicense -UserId "jsmith@contoso.com" -AddLicenses @{SkuId="<License-SKU-ID>"} -RemoveLicenses @() |
| 278 | +``` |
| 279 | + |
| 280 | +### 5. Verify Mailbox Provisioning |
| 281 | +```powershell |
| 282 | +Connect-ExchangeOnline |
| 283 | +
|
| 284 | +# Check if mailbox exists |
| 285 | +Get-Mailbox -Identity "jsmith@contoso.com" |
| 286 | +
|
| 287 | +# May take 30-60 minutes for mailbox to provision |
| 288 | +``` |
| 289 | + |
| 290 | +### 6. Test Mail Flow |
| 291 | +Send test email to verify mailbox is functioning correctly. |
| 292 | + |
| 293 | +## When to Use This Script |
| 294 | + |
| 295 | +### Required Scenarios |
| 296 | +- **Decommissioning on-premises Exchange** after full migration to Exchange Online |
| 297 | +- **Moving to Exchange Online without hybrid** configuration |
| 298 | +- **Fixing orphaned Exchange attributes** from previous failed migrations |
| 299 | +- **Preparing users for cloud-only mailboxes** after data migration |
| 300 | +- **Resolving "mailbox already exists"** errors in Exchange Online |
| 301 | + |
| 302 | +### Not Recommended For |
| 303 | +- **Active hybrid Exchange environments** - use proper migration tools instead |
| 304 | +- **Users with active on-premises mailboxes** - migrate data first |
| 305 | +- **Environments with Exchange Online Hybrid** - use New-MoveRequest |
| 306 | +- **Production without testing** - always test with -WhatIf first |
| 307 | + |
| 308 | +## Important Warnings |
| 309 | + |
| 310 | +⚠️ **Data Loss Prevention**: |
| 311 | +- Always backup before running (script does this automatically) |
| 312 | +- Test with `-WhatIf` first |
| 313 | +- Verify backup file was created successfully |
| 314 | +- This disconnects users from on-premises Exchange mailboxes |
| 315 | + |
| 316 | +⚠️ **Prerequisites**: |
| 317 | +- Ensure all mailbox data has been migrated to Exchange Online |
| 318 | +- Verify users have appropriate Exchange Online licenses |
| 319 | +- Confirm Azure AD Connect is functioning properly (if hybrid) |
| 320 | + |
| 321 | +⚠️ **Cannot Be Undone Without Backup**: |
| 322 | +- Once attributes are cleared, on-premises mailbox link is permanently broken |
| 323 | +- Use `-RestoreFromBackup` to rollback if needed |
| 324 | +- Keep backup files in secure location |
| 325 | + |
| 326 | +## Related Scripts |
| 327 | +- [Get-ComprehensiveADReport.ps1](../../On%20Premise/Get-ComprehensiveADReport.md) - Assess AD environment before migration |
| 328 | +- [Get-MailboxPermissionsReport.ps1](../../Assessments/Microsoft365/Get-MailboxPermissionsReport.md) - Document mailbox permissions |
| 329 | +- [New-Office365Accounts.ps1](../../Office365/New-Office365Accounts.md) - Create Exchange Online mailboxes |
| 330 | + |
| 331 | +## Version History |
| 332 | +- **v1.0** (2026-02-02): Initial release |
| 333 | + - Core functionality for removing Exchange attributes |
| 334 | + - Backup and restore capabilities |
| 335 | + - Support for single user, OU, and bulk CSV processing |
| 336 | + - WhatIf support and comprehensive error handling |
| 337 | + - Improved attribute detection for accurate removal |
| 338 | + |
| 339 | +## See Also |
| 340 | +- [Microsoft: Decommission on-premises Exchange servers](https://docs.microsoft.com/en-us/exchange/decommission-on-premises-exchange) |
| 341 | +- [Microsoft: Exchange Online mailbox migration](https://docs.microsoft.com/en-us/exchange/mailbox-migration/mailbox-migration) |
| 342 | +- [Azure AD Connect sync](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sync-whatis) |
0 commit comments