M365 Migration Outlook Repair Toolkit

Repairing the client side after an on-premises Exchange to Microsoft 365 cutover.

Language
PowerShell 5.1
Privileges
Standard user
Dependencies
None
View on GitHub

The problem this exists for

The mailbox moves cleanly. The server side reports success. Then Monday arrives and a third of the users cannot open Outlook, and every one of them describes it differently: a password box that will not accept the right password, a client stuck on disconnected, an error saying it cannot reach an Exchange server that no longer exists.

None of that is a migration failure. It is the client refusing to accept that the mailbox moved, for four distinct reasons that look identical from the help desk.

The four root causes

  • Cached credentials. Windows still holds a stored password for the old server, so Outlook keeps presenting it, keeps getting rejected, and keeps asking the user to type it again. The user is not wrong. The credential store is.
  • Autodiscover cache and registry redirects. The client resolves to the deprecated infrastructure because a cached XML file or a registry redirect answers before anything else gets a chance. This is the one that survives a reboot and outlives most attempts to fix it.
  • Modern authentication disabled by policy. An old policy key suppresses the Microsoft 365 sign in interface entirely, so the user never sees the window they need to complete.
  • Broken MAPI profiles. The profile is bound to a server that is gone. No amount of credential clearing helps, because the profile itself has to be rebuilt.

Any one of these produces a ticket. Two of them together produce a ticket that gets escalated, because the first fix appears to work and then the symptom returns the next morning.

Design constraints

Two constraints shaped everything.

It has to run as a standard user. If the tool needs administrator rights, it needs a deployment mechanism, an approval, and a person from the team to run it. That turns a two minute fix into a scheduled visit. Every repair in the toolkit was chosen or rewritten so it works in the user's own context.

It has to have no dependencies. PowerShell 5.1, which ships with Windows, and nothing else. No modules to install, no execution policy negotiation, no version drift between machines. A user double clicks a .cmd file and the thing runs.

The safety model

This is a tool that deletes Outlook profiles and edits the registry on machines belonging to people who did not ask for it. The safety design is not a feature, it is the price of being allowed to exist.

  • Dry run previews come before any modification, and dry run is the default posture rather than an opt in.
  • The registry is backed up before an edit, not after the decision to edit.
  • Every written value is read back and verified. A write that silently failed is worse than one that loudly failed, because it is reported as a fix.
  • PST inventory is saved before profile removal, so nothing detaches a file that nobody remembers was attached.
  • The script exits with code 1 on failure. It never reports success it did not achieve.

That last point is the one I would argue for hardest. A repair script that always exits zero is worse than no script, because it converts a visible problem into a machine that has been marked as fixed.

The eight repair steps

  • Remove cached credentials. Clears the stored passwords still pointing at the decommissioned server.
  • Sign out the old Office identity. Drops the licensing identity tied to the previous tenant.
  • Correct registry policy. Re-enables modern authentication where policy disabled it.
  • Clear the Autodiscover cache. Removes cached XML and registry redirects pointing at old infrastructure.
  • Inventory profiles. Lists every MAPI profile before anything is touched.
  • Rebuild the broken profile. Removes the profile behind "cannot connect to Exchange server".
  • Reattach PST files. Saves the inventory first, then reattaches to the rebuilt profile.
  • Report device state. Prints Entra join and registration state, usually the answer when one machine behaves differently.

Two entry points, two audiences

End users get START.cmd to repair and DIAGNOSE.cmd to collect information. Two files, no parameters, no decisions.

Administrators get the underlying script with real control:

.\Fix-M365MigrationOutlook.ps1 -Steps All -DryRun
.\Fix-M365MigrationOutlook.ps1 -Steps All -Force
.\Fix-M365MigrationOutlook.ps1 -RemoveProfile 'Outlook'
.\Fix-M365MigrationOutlook.ps1 -OldAccount 'user@olddomain.com'
.\Fix-M365MigrationOutlook.ps1 -CachedMode Off

Splitting the interfaces this way was the single most useful decision. The user facing path cannot do anything dangerous because it cannot be given a dangerous instruction, and the administrator path does not have to be defensive about a user pasting a flag they read in a forum.

What it is made of

  • Fix-M365MigrationOutlook.ps1 is the repair engine.
  • Test-Blocker.ps1 collects diagnostics without changing anything, which is what you want in hand before you decide what to change.
  • START.cmd and DIAGNOSE.cmd are the user entry points.
  • A Pester test suite, because a script that edits the registry on other people's machines should have tests, and because it is the only way to keep the dry run path honest as the tool grows.

What I would change

The step selection is a flat list. In practice the steps have an order and some of them make others unnecessary, and the tool does not know that. Running everything is safe but slower than it needs to be, and a smarter version would diagnose first and then run only the steps the diagnosis implicates.

That is the next version. The current one is deliberately dumb, and being dumb is why I trust it on a machine I cannot see.

The transferable part If a fix requires administrator rights, it will not get run at the moment it is needed. Design the repair for the privileges the person in front of the machine already has.

Read next

Tell me what is breaking.

Migration work, an estate that has outgrown its last design, or a question about the toolkit. All of it is welcome.

Follow the writing

Prefer RSS? Subscribe to the feed.