EXO-Migration ohne Remote Move
Wie lokale Exchange-Mailboxen kontrolliert als neue, leere Exchange-Online-Mailboxen bereitgestellt werden: PST-Sicherung, CSV-Freigabe, RemoteMailbox, Synchronisation, Validierung und Rollback.
Ein Hybrid Remote Move ist der normale Weg, um ein lokales Exchange-Postfach mitsamt Inhalt nach Exchange Online zu verschieben. Nicht jede Organisation erlaubt diesen Migrationspfad. Wenn eine Sicherheitsrichtlinie Remote Moves ausschliesst, kann ein bewusst anderer Ansatz vertretbar sein: Das lokale Postfach wird als PST gesichert, vom synchronisierten AD-Benutzer getrennt und für denselben Benutzer wird eine neue, leere Mailbox in Exchange Online bereitgestellt.
Dieser Weg ist keine Mailbox-Migration. Er überträgt weder Nachrichten noch Kalender, Regeln oder Berechtigungen in die Cloud. Die PST dient ausschliesslich als Sicherung und wird in diesem Szenario nicht importiert. Der Ablauf eignet sich daher nur, wenn eine leere Ziel-Mailbox fachlich akzeptiert und der Verlust der aktiven Postfachkonfiguration ausdrücklich freigegeben ist.
Zielzustand und harte Voraussetzungen
Nach dem Cutover bleibt derselbe AD-Benutzer bestehen. Lokal wird er jedoch nicht mehr als UserMailbox, SharedMailbox, RoomMailbox oder EquipmentMailbox, sondern als RemoteMailbox verwaltet. Nach der Synchronisation repräsentiert dieses Objekt die neue Mailbox in Exchange Online.
Der gewünschte Zustand sieht so aus:
- Das lokale Postfach ist vollständig als PST gesichert.
- Das lokale Postfach ist getrennt, aber innerhalb der konfigurierten Retention noch nicht endgültig gelöscht.
- Der bestehende AD-Benutzer ist als RemoteMailbox aktiviert.
- Primäre Adresse, Aliase und der alte
LegacyExchangeDNbleiben erhalten. - Entra Connect hat die Änderungen synchronisiert.
- Für Benutzerpostfächer ist ein Exchange-Online-Serviceplan zugewiesen.
- Exchange Online zeigt ein echtes Cloud-Postfach und der Mailflow endet dort.
Vor dem Start müssen ausserdem geklärt sein:
- Die PST-Freigabe ist per UNC erreichbar. Die Gruppe
Exchange Trusted Subsystembesitzt dort Lese- und Schreibrechte. - Das ausführende Konto hat die Management-Rolle
Mailbox Import Export. - Die PST ist nur die vereinbarte Sicherung; es ist kein späterer Import eingeplant.
- Aufbewahrung, Litigation Hold, eDiscovery und regulatorische Vorgaben sind separat geprüft.
- Stellvertretungen, Send-As, Send-on-Behalf, Weiterleitungen, Inbox-Regeln, mobile Geräte und Applikationszugriffe sind inventarisiert.
- Während Export und Umschaltung werden eingehende Nachrichten am vorgelagerten Gateway kontrolliert zurückgehalten. Benutzer und Anwendungen dürfen nicht mehr in das Quellpostfach schreiben.
- Die Retention der lokalen Mailbox-Datenbank deckt das Rollback-Fenster ab.
Warum eine CSV-Freigabeliste unverzichtbar ist
Eine direkte Pipeline wie Get-Mailbox | Disable-Mailbox ist für diesen Vorgang zu riskant. Sie würde auch System-, Discovery- oder anderweitig nicht freigegebene Postfächer erfassen können. Der folgende Ablauf arbeitet deshalb mit zwei expliziten Freigaben:
Action=CUTOVERbestimmt, welche Zeile tatsächlich umgestellt werden darf.PstVerified=YESbestätigt, dass die Exportdatei technisch und organisatorisch geprüft wurde.
Zuerst wird nur das Inventar erzeugt:
$CsvPath = "C:\Migration\mailboxes.csv"
$RemoteRoutingDomain = "contoso.mail.onmicrosoft.com"
Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails `
UserMailbox,SharedMailbox,RoomMailbox,EquipmentMailbox |
Sort-Object PrimarySmtpAddress |
ForEach-Object {
[pscustomobject]@{
Identity = $_.Identity
DisplayName = $_.DisplayName
PrimarySmtpAddress = $_.PrimarySmtpAddress.ToString()
Alias = $_.Alias
SourceType = $_.RecipientTypeDetails.ToString()
ArchiveStatus = $_.ArchiveStatus.ToString()
ServerName = $_.ServerName
Database = $_.Database.ToString()
RemoteRoutingAddress = "$($_.Alias)@$RemoteRoutingDomain"
Action = "REVIEW"
PstVerified = "NO"
}
} |
Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8
Die Datei wird anschliessend fachlich bereinigt. Nur tatsächlich freigegebene Postfächer erhalten Action=CUTOVER. Systemmailboxen und Sonderobjekte gehören nicht in diese Liste.
Phase 1: Primärpostfach und Archiv als PST sichern
New-MailboxExportRequest schreibt nur auf einen UNC-Pfad. Für jedes Postfach wird ein eindeutiger Dateiname erzeugt. Ein aktives Online-Archiv des lokalen Exchange wird separat exportiert:
$CsvPath = "C:\Migration\mailboxes.csv"
$PstShare = "\\fileserver\exchange-pst$"
$BatchName = "EXO-NewMailbox-20260807"
$targets = Import-Csv $CsvPath | Where-Object Action -eq "CUTOVER"
foreach ($row in $targets) {
$safeName = ($row.PrimarySmtpAddress -replace '[^a-zA-Z0-9@._-]', '_')
$primaryPath = "$PstShare\$safeName.pst"
New-MailboxExportRequest `
-Mailbox $row.Identity `
-FilePath $primaryPath `
-Name "Primary-$safeName" `
-BatchName $BatchName
if ($row.ArchiveStatus -eq "Active") {
New-MailboxExportRequest `
-Mailbox $row.Identity `
-IsArchive `
-FilePath "$PstShare\$safeName-archive.pst" `
-Name "Archive-$safeName" `
-BatchName $BatchName
}
}
Der Export ist erst freigegeben, wenn jeder Request den Status Completed hat:
Get-MailboxExportRequest -BatchName $BatchName |
Get-MailboxExportRequestStatistics -IncludeReport |
Format-Table DisplayName,Status,PercentComplete,FailureCode,Message -AutoSize
Get-MailboxExportRequest -BatchName $BatchName |
Where-Object Status -ne "Completed"
Zusätzlich sind Existenz, Grösse, Lesbarkeit, Backup-Übernahme und Zugriffsschutz der Dateien zu prüfen. Erst danach wird für die entsprechende CSV-Zeile PstVerified=YES gesetzt.
Phase 2: Postfachdaten und Exchange-Attribute sichern
Vor der ersten Änderung wird pro Postfach ein maschinenlesbarer Snapshot erstellt. Er ist wichtiger als ein Screenshot, weil Aliase, GUIDs und der LegacyExchangeDN später exakt rekonstruiert werden können:
$SnapshotPath = "C:\Migration\Snapshots"
New-Item -ItemType Directory -Path $SnapshotPath -Force | Out-Null
Import-Csv "C:\Migration\mailboxes.csv" |
Where-Object { $_.Action -eq "CUTOVER" -and $_.PstVerified -eq "YES" } |
ForEach-Object {
$mailbox = Get-Mailbox -Identity $_.Identity
$safeName = ($_.PrimarySmtpAddress -replace '[^a-zA-Z0-9@._-]', '_')
$mailbox |
Select-Object Identity,DistinguishedName,ExchangeGuid,ArchiveGuid,
RecipientTypeDetails,PrimarySmtpAddress,EmailAddresses,
LegacyExchangeDN,Alias,Database,ServerName |
Export-Clixml "$SnapshotPath\$safeName.xml"
}
Delegationen und Weiterleitungen benötigen eigene Exporte. Mindestens diese Informationen sollten separat gesichert werden:
$mailbox = Get-Mailbox -Identity user01@contoso.com
$mailbox | Format-List ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward
Get-MailboxPermission -Identity $mailbox.Identity
Get-ADPermission -Identity $mailbox.DistinguishedName
Get-InboxRule -Mailbox $mailbox.Identity
Get-CalendarProcessing -Identity $mailbox.Identity -ErrorAction SilentlyContinue
Diese Konfigurationen wechseln nicht automatisch auf die neue Cloud-Mailbox.
Phase 3: Lokale Mailbox trennen und RemoteMailbox aktivieren
Der eigentliche Cutover ist kurz, aber folgenreich. Disable-Mailbox entfernt die Exchange-Attribute vom AD-Benutzer und trennt das lokale Postfach. Die Mailbox-Daten bleiben bis zum Ablauf der Datenbank-Retention als disconnected mailbox erhalten. Direkt danach aktiviert Enable-RemoteMailbox denselben AD-Benutzer für Exchange Online.
Das folgende Skript verarbeitet ausschliesslich doppelt freigegebene Zeilen. Es bewahrt die primäre SMTP-Adresse, alle bestehenden Proxy-Adressen und den alten LegacyExchangeDN als X500-Adresse. Der X500-Eintrag verhindert NDRs bei Antworten auf ältere Nachrichten oder bei alten Outlook-Autocomplete-Einträgen.
$CsvPath = "C:\Migration\mailboxes.csv"
$PstShare = "\\fileserver\exchange-pst$"
$targets = Import-Csv $CsvPath |
Where-Object { $_.Action -eq "CUTOVER" -and $_.PstVerified -eq "YES" }
foreach ($row in $targets) {
$safeName = ($row.PrimarySmtpAddress -replace '[^a-zA-Z0-9@._-]', '_')
$pstPath = "$PstShare\$safeName.pst"
if (-not (Test-Path $pstPath)) {
throw "PST fehlt: $pstPath"
}
if ((Get-Item $pstPath).Length -eq 0) {
throw "PST ist leer: $pstPath"
}
$mailbox = Get-Mailbox -Identity $row.Identity -ErrorAction Stop
$primary = $mailbox.PrimarySmtpAddress.ToString()
$legacyDn = $mailbox.LegacyExchangeDN
if ($primary -ine $row.PrimarySmtpAddress) {
throw "Primaere SMTP-Adresse stimmt nicht mit der Freigabeliste ueberein: $($row.Identity)"
}
$preservedAddresses = @($mailbox.EmailAddresses | ForEach-Object ToString)
Disable-Mailbox -Identity $row.Identity -Confirm:$false
$enableParams = @{
Identity = $row.Identity
Alias = $row.Alias
PrimarySmtpAddress = $primary
RemoteRoutingAddress = $row.RemoteRoutingAddress
ACLableSyncedObjectEnabled = $true
}
switch ($row.SourceType) {
"SharedMailbox" { $enableParams.Shared = $true }
"RoomMailbox" { $enableParams.Room = $true }
"EquipmentMailbox" { $enableParams.Equipment = $true }
"UserMailbox" { }
default { throw "Nicht unterstuetzter Mailbox-Typ: $($row.SourceType)" }
}
Enable-RemoteMailbox @enableParams
$orderedAddresses = @(
"SMTP:$primary"
$preservedAddresses |
Where-Object { $_ -notmatch '^SMTP:' -or $_.Substring(5) -ine $primary }
"smtp:$($row.RemoteRoutingAddress)"
"X500:$legacyDn"
)
$seen = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::OrdinalIgnoreCase
)
$finalAddresses = foreach ($address in $orderedAddresses) {
if ($seen.Add($address)) { $address }
}
Set-RemoteMailbox -Identity $row.Identity -EmailAddressPolicyEnabled $false
Set-RemoteMailbox -Identity $row.Identity -EmailAddresses $finalAddresses
Set-RemoteMailbox -Identity $row.Identity -PrimarySmtpAddress $primary
Get-RemoteMailbox -Identity $row.Identity |
Format-List DisplayName,RecipientTypeDetails,PrimarySmtpAddress,
RemoteRoutingAddress,EmailAddresses
}
Das Skript ist absichtlich kein vollautomatisches Migrationswerkzeug. Es beendet den Lauf beim ersten Widerspruch, damit ein Administrator Ursache und Zustand beurteilen kann. Vor einem produktiven Batch sollte der Code mit wenigen Testpostfächern und den eingesetzten Exchange-Versionen validiert werden.
Phase 4: Synchronisieren, lizenzieren und verifizieren
Nach der lokalen Änderung wird auf dem Entra-Connect-Server ein Delta-Zyklus gestartet:
Start-ADSyncSyncCycle -PolicyType Delta
Für Benutzerpostfächer muss anschliessend ein gültiger Exchange-Online-Serviceplan zugewiesen sein, beispielsweise über gruppenbasierte Lizenzierung. Shared-, Raum- und Gerätepostfächer sind nach den aktuellen Microsoft-Lizenzbedingungen und den benötigten Funktionen zu beurteilen.
Die Provisionierung ist asynchron. Microsoft nennt für normale Änderungen meist weniger als 30 Minuten, in einzelnen Fällen jedoch bis zu 24 Stunden. Während dieser Zeit sollte der vorgelagerte Mailflow Nachrichten kontrolliert zurückhalten, statt sie an ein noch nicht bereites Ziel zuzustellen.
Die lokale Kontrolle muss nun eine RemoteMailbox zeigen:
Get-RemoteMailbox -Identity user01@contoso.com |
Format-List RecipientTypeDetails,PrimarySmtpAddress,RemoteRoutingAddress,EmailAddresses
Get-Mailbox -Identity user01@contoso.com -ErrorAction SilentlyContinue
In Exchange Online wird geprüft, ob aus dem bisherigen MailUser ein echtes Postfach geworden ist:
Get-EXORecipient -Identity user01@contoso.com |
Format-List RecipientTypeDetails,PrimarySmtpAddress,EmailAddresses
Get-EXOMailbox -Identity user01@contoso.com |
Format-List RecipientTypeDetails,PrimarySmtpAddress,ExchangeGuid
Der Batch gilt erst als abgeschlossen, wenn zusätzlich folgende Tests erfolgreich sind:
- Zustellung von extern und intern
- Versand nach extern und intern
- Antwort auf eine alte Nachricht, um die X500-Adresse zu prüfen
- Anmeldung mit Outlook und Outlook im Web
- Stellvertretungen und Send-As
- Weiterleitungen und Transportregeln
- Raum- und Gerätebuchungen
- Anwendungen, Scanner und SMTP-Relays
- Message Trace mit Zustellung an die neue Cloud-Mailbox
Rollback und Aufräumen
Das lokale Quellpostfach darf während der Validierungsphase nicht mit Remove-StoreMailbox gelöscht werden. Solange es innerhalb der Mailbox-Retention als disconnected mailbox vorhanden ist, besteht noch eine technische Rückfallmöglichkeit. Ein Rollback erfordert jedoch eine kontrollierte Umkehr der RemoteMailbox-Attribute und das erneute Verbinden der lokalen Mailbox; gleichzeitig muss verhindert werden, dass zwei aktive Zustellziele entstehen.
Vor einem Rollback sind deshalb Mailflow, Synchronisationszustand und bereits in der Cloud eingegangene Nachrichten zu sichern. Ein Rückwechsel ist kein einfacher Einzeiler und gehört als getestetes Runbook zum Change.
Nach erfolgreicher Abnahme werden Export-Requests bereinigt, PST-Dateien gemäss Schutz- und Aufbewahrungskonzept archiviert und temporäre Berechtigungen auf der Exportfreigabe entfernt:
Get-MailboxExportRequest -BatchName $BatchName |
Remove-MailboxExportRequest -Confirm:$false
Die disconnected mailboxes sollten erst nach Ablauf des vereinbarten Rollback-Fensters und gemäss Retention-Konzept endgültig bereinigt werden.
Fazit
Wenn Hybrid Remote Moves nicht erlaubt sind und keine Postfachdaten in Exchange Online übernommen werden müssen, lässt sich ein bestehender synchronisierter AD-Benutzer kontrolliert von einer lokalen Mailbox auf eine neue Cloud-Mailbox umstellen. Der kritische Teil ist nicht Enable-RemoteMailbox, sondern die Prozesskontrolle darum herum: vollständige Inventarisierung, verifizierte PST-Sicherung, explizite Freigaben, Erhalt der Proxy- und X500-Adressen, ein kontrollierter Mailflow sowie ein echtes Rollback-Fenster.

Kommentare
Die Kommentare werden von GitHub / Giscus geladen.