Portfolio / Automation & Process Design
M365 tenant migration | Exchange Online | PowerShell | Microsoft Graph
Background
During a large-scale M365 tenant migration spanning 200+ locations, hundreds of shared mailboxes, distribution lists, M365 groups, and resource accounts needed to be consolidated, renamed, or decommissioned across domain transitions. Each object type required a different disposition: rename it, delete it, consolidate it into another account, move its email aliases elsewhere, or leave it alone.
The original process relied on decisions made verbally or from memory during execution. That led to inconsistencies, missed accounts, and mistakes that required manual remediation. The same decisions got relitigated across every migration wave because nothing was formally documented until after the fact.
How It Works
The architecture separates planning, review, and execution into distinct stages with an enforced checkpoint between each. No changes reach the environment until the action plan has been reviewed and confirmed.
Performs automated discovery of all shared mailboxes, distribution lists, M365 groups, and resource accounts across target domains via Exchange Online PowerShell. Generates a structured Excel workbook: a full inventory sheet and a planning sheet with per-account-type dropdown menus and formula-driven columns that auto-populate based on the selected plan.
Reads the completed planning sheet and translates every plan selection into a structured, human-readable action list showing exactly what will happen to each account before anything is touched. Output is meant to be reviewed and confirmed before proceeding, and shared with stakeholders if needed.
Executes the approved action plan idempotently, in a defined phase order. Renames accounts, updates email addresses, moves aliases, copies permissions, handles consolidations, creates inbox rules, and removes accounts marked for deletion, consistently and without manual intervention.
Stage 1 Detail
A key design decision was that dropdown options are scoped to the account type. A shared mailbox has different valid plans than a distribution list or an M365 group, so the dropdown only shows options that are actually applicable. Once a plan is selected, the New Display Name, New Email, and Notes columns auto-populate with either a calculated value, a placeholder prompting for remaining input, or a warning flagging something that requires manual attention before Apply runs.
| Display Name | Primary Email | Account Type | Plan | New Display Name | New Email | Notes |
|---|---|---|---|---|---|---|
| HR Team | hr@legacy.corp | Shared Mailbox | Rename | -- Enter New Display Name -- | -- Enter New Email -- | |
| All Staff | allstaff@legacy.corp | Distribution List | Rename | -- Enter New Display Name -- | -- Enter New Email -- | |
| Marketing Hub | marketing@legacy.corp | Unified Group (M365) | SP Moving / Mailbox Depreciate+MoveAlias | -- Enter New Display Name -- | -- Enter New Email -- | !! Enter alias target |
| Legacy Alerts | alerts@legacy.corp | Distribution List | Delete | N/A | N/A | |
| Info - Downtown | info-downtown@legacy.corp | Shared Mailbox | Consolidation - Secondary | -- Enter New Display Name -- | -- Enter New Email -- | !! Enter consolidation target in New Email |
| Noreply | noreply@legacy.corp | Shared Mailbox | No Change | Noreply | noreply@legacy.corp | |
| Conference Room A | confroom-a@legacy.corp | Room (Resource) | -- Choose Plan -- | -- Pending -- | -- Pending -- | -- Pending -- |
Sample data with fictional domains. Dropdown options and color coding vary by account type.
Stage 2 Detail
Before any change runs, the Stamp script reads the completed planning sheet and produces a structured action list broken into numbered phases. The phase order is intentional: aliases have to be freed by deletes and depreciations before they can be copied to target accounts, and inbox rules are always created last so the folder structure is in place when they run.
When multiple source accounts target the same destination with the same action type, the Stamp script merges them into a single row with comma-delimited values, keeping the action plan clean and reducing redundant operations at apply time. Inbox rules are the deliberate exception to this.
Engineering Details
A few of the non-obvious engineering constraints that shaped the design:
When a shared mailbox is marked for consolidation, the scripts handle the Exchange-side work: aliases, permissions, inbox rules. But the mailbox data itself has to move via separate tooling. Rather than managing that list manually, the Stamp script was designed to auto-generate an import row for every Consolidation plan, keeping the migration job queue in sync with the action plan with no extra step.
When copying members or owners to a target account, the correct operation depends on what type of object the target is. SMB target: GrantFullAccess + GrantSendAs. Group target: AddMember + AddOwner. DL target: AddMember + SetManagedBy. The scripts resolve target type at runtime and apply the right operation automatically, with no manual adjustment per account.
Deleting an M365 group deletes its SharePoint site with it. For groups where SP content needs to stay accessible, the depreciation plans keep the group alive in a stripped state: aliases removed, email and display name updated to signal deprecated status, so the SharePoint site remains reachable through the transition period without blocking alias reassignment.
My Role