在共存阶段,Exchange Online 的PF设置的是使用远程的公用文件夹,即On-prem Exchange Server的公用文件夹。当所有邮箱都迁移至Exchange Online之后,我们便可以开始公用文件夹(Public Folder 本文将简称为PF)的迁移。迁移完成之后,Exchange Online改为使用本地的PF, 而On-prem Exchange Server设置成使用远程的PF。
本文记录的是参照微软的TechNet文章使用批次迁移将 Exchange 服务器公用文件夹迁移到 Exchange Online迁移Exchange 2016 PF至Exchange Online的过程,此步骤适用于Exchange 2013/2016/2019, Exchange 2010则有所不同。
迁移过程概述
从Exchange 2013开始,公用文件夹的数据存放在公用文件夹邮箱中。因此其迁移过程和邮箱迁移有些类似,但也有些不同。
迁移公用文件夹总体可分成3个阶段:
- 准备阶段,对Exchange 服务器上现有的PF数据进行分析、备份,在Exchange Online端创建新的PF 邮箱,用于存放PF数据
- 创建/启动PF迁移批处理,通过PowerShell创建PF的迁移终结点、迁移批处理。随后后台开始数据同步。此阶段用户使用不受影响,可继续使用PF。
- 完成迁移请求。这需要预约公用文件夹的服务中段时间,锁定PF访问,完成切换。切换之后,所有用户将连接到Exchange Online的公用文件夹。在完成最终步骤之前,用户将无法使用PF。
与邮箱迁移相同处:
- 管理员需要创建一个专用于PF的迁移终结点(Migration Endpoint)
- 管理员创建一个PF迁移批处理,开始数据同步
- Exchange Online后台连接到Exchange On-prem 的MRS, 进行PF数据同步
- 在数据同步期间,用户可以继续访问原有的On-prem的Exchange Server上的公用文件夹
与邮箱迁移不同处:
- 在准备阶段,需要先通过Exchange Online PowerShell创建用于存放PF数据的PF 邮箱
- 创建PF迁移终结点、迁移批处理需要使用PowerShell命令,不能在ECP中操作
- 所有的PF数据迁移在同一个迁移批处理中完成。而用户邮箱则可以分成多个迁移批处理
将微软文章中的各步骤以划分阶段的方式总结如下。
根据项目经验,我建议将原文中先决条件步骤中的创建远程接收域部分保留至完成迁移之后再做,否则可能导致发送到mail enabled PF的邮件被拒,收到NDR。
在启动PF迁移阶段,以及完成迁移之后,Outlook客户端的连接示意如下:
迁移脚本
TechNet中的文章,比较清晰地写明了迁移的具体步骤,可以阅读原文了解每一步的最详细描述。
为了更方便操作,可将需要在本地 Exchange 2016 Server上运行的PowerShell 命令,以及需要在Exchange Online上运行的PowerShell命令分别保存在两个不同的PS1文件中,然后用2个Windows PowerShell ISE窗口分别打开、逐行运行。 可将两个ISE窗口的背景设成不同的颜色,以作区分是连接到本地Exchange Server还是Exchange Online。
1. 在Exchange 2016上执行的步骤
提示:
1) 可以通过以下命令在Windows PowerShell ISE中导入Exchange Module,从而能够执行Exchange 的PowerShell 命令。
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
2) 原文中步骤2获取PF快照生成的是XML文件,管理员很难阅读分析数据。可以将导出文件部分的Export-CliXML命令改成Export-CSV, 生成CSV文件,这样便于使用Excel来分析PF的数据,例如公有多少PF文件夹、各自大小、哪些是启用了邮件的。
3) 在锁定PF期间,发往mail enabled PF的邮件会延迟投递,保留在Exchange 的传输队列中。可以使用Exchange管理工具Queue Viewer查看到这些邮件,使用以下步骤4)中的命令对其进行备份。当完成最终启用Exchange Online的PF约30分钟之后,邮件会被投递到目的PF中。这期间可能会出现邮件从Exchange 2016的Queue Viewer中消失,但还未到PF的情况,等待约30分钟即可。
4)步骤9中备份邮件的以下PowerShell命令,在Windows PowerShell ISE中执行会出错,需要在Exchange Mangement Shell中执行。此外$Temp变量中需要提供完整的文件路径,并确保文件夹存在,例如$Temp="C:\PFMail\"。
#步骤 9:备份队列中发送到已启用邮件的公用文件夹的电子邮件
$Server=Get-TransportService;ForEach ($t in $server) {Get-Message -Server $t -ResultSize Unlimited| ?{$_.Recipients -like "*PF.InTransit*"} | ForEach-Object {Suspend-Message $_.Identity -Confirm:$False; $Temp="C:\PFMail\"+$_.InternetMessageID+".eml"; $Temp=$Temp.Replace("<","_"); $Temp=$Temp.Replace(">","_"); Export-Message $_.Identity | AssembleMessage -Path $Temp;Resume-message $_.Identity -Confirm:$false}}
#在本地 Exchange 2016 上运行
#导入PowerShell Exchange Module
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
#步骤 2:准备迁移
#获取当前公用文件夹快照
Get-PublicFolder -Recurse -ResultSize Unlimited | Export-CliXML OnPrem_PFStructure.xml
Get-PublicFolderStatistics -ResultSize Unlimited | Export-CliXML OnPrem_PFStatistics.xml
Get-PublicFolder -Recurse -ResultSize Unlimited | Get-PublicFolderClientPermission | Select-Object Identity,User,AccessRights -ExpandProperty AccessRights | Export-CliXML OnPrem_PFPerms.xml
Get-MailPublicFolder -ResultSize Unlimited | Export-CliXML OnPrem_MEPF.xml
Get-PublicFolder -Recurse -ResultSize Unlimited | Export-CSV OnPrem_PFStructure.csv
Get-PublicFolderStatistics -ResultSize Unlimited | Export-CSV OnPrem_PFStatistics.csv
Get-PublicFolder -Recurse -ResultSize Unlimited | Get-PublicFolderClientPermission | Select-Object Identity,User,AccessRights -ExpandProperty AccessRights | Export-CSV OnPrem_PFPerms.csv
Get-MailPublicFolder -ResultSize Unlimited | Export-CSV OnPrem_MEPF.csv
#查看是否有含反斜杠的公用文件夹
Get-PublicFolder -Recurse -ResultSize Unlimited | Where {$_.Name -like "*\*" -or $_.Name -like "*/*"} | Format-List Name, Identity, EntryId
#检查是否存在之前的任何迁移过程,以及这些迁移的状态
Get-OrganizationConfig | Format-List PublicFolderMailboxesLockedForNewConnections, PublicFolderMailboxesMigrationComplete
#步骤3:生成.csv 文件
#创建文件夹名称到文件夹大小的映射文件
.\Export-ModernPublicFolderStatistics.ps1 stats.csv
#将源公用文件夹映射到目标公用文件夹Exchange Online邮箱
.\ModernPublicFolderToMailboxMapGenerator.ps1 -MailboxSize 50GB -MailboxRecoverableItemSize 1GB -ImportFile .\stats.csv -ExportFile map.csv
#编辑 map.csv 并为 Exchange Online 中的目标公用文件夹邮箱提供唯一的名称
#步骤 5:启动迁移请求
#此脚本将启用了邮件的公用文件夹从本地 Active Directory 同步到 Exchange Online,Credential是Exchange Online用户帐户。
.\Sync-ModernMailPublicFolders.ps1 -Credential (Get-Credential) -CsvSummaryFile:sync_summary.csv
#查找存有PF主层次结构邮箱的 GUID
(Get-OrganizationConfig).RootPublicFolderMailbox.HierarchyMailboxGuid.GUID
#===============================Ex2016 步骤 -- 完成PF 迁移,需预约服务中断时间=================================================
#导入PowerShell Exchange Module
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
#运行步骤2中的PF Inventory 脚本,获取本地公用文件夹结构、统计信息、权限的快照
#步骤 6: 锁定Exchange 2013/16/19/上的公用文件夹
Set-OrganizationConfig -PublicFolderMailboxesLockedForNewConnections $true
#在本地环境中运行以下命令以确保公用文件夹已锁定,预期结果"Couldn't find the public folder mailbox."
Get-PublicFolder \
#步骤 7:完成公用文件夹迁移
#确认本地部署环境中没有其他公用文件夹邮箱移动或公用Exchange移动。
Get-MoveRequest
Get-PublicFolderMoveRequest
#重新运行以下脚本,以确保任何启用邮件的新公用文件夹与Exchange Online同步,Credential是Exchange Online帐户。
.\Sync-ModernMailPublicFolders.ps1 -Credential (Get-Credential) -CsvSummaryFile:sync_summary.csv
#步骤 9:完成本地迁移,在完成Exchange Online端的步骤8后再执行
#备份队列中发送到已启用邮件的公用文件夹的电子邮件
$Server=Get-TransportService;ForEach ($t in $server) {Get-Message -Server $t -ResultSize Unlimited| ?{$_.Recipients -like "*PF.InTransit*"} | ForEach-Object {Suspend-Message $_.Identity -Confirm:$False; $Temp="C:\PFMail\"+$_.InternetMessageID+".eml"; $Temp=$Temp.Replace("<","_"); $Temp=$Temp.Replace(">","_"); Export-Message $_.Identity | AssembleMessage -Path $Temp;Resume-message $_.Identity -Confirm:$false}}
#为mail enabled PF添加接受域,邮件路由至EXO
#New-AcceptedDomain -Name PublicFolderDestination_78c0b207_5ad2_4fee_8cb9_f373175b3f99 -DomainName <target domain> -DomainType InternalRelay
New-AcceptedDomain -Name PublicFolderDestination_78c0b207_5ad2_4fee_8cb9_f373175b3f99 -DomainName "M365B973018.mail.onmicrosoft.com" -DomainType InternalRelay
#Get-AcceptedDomain | Where {$_.DomainName -eq "<target domain>"}
Get-AcceptedDomain | Where {$_.DomainName -eq "M365B973018.mail.onmicrosoft.com"} | Set-AcceptedDomain -Name PublicFolderDestination_78c0b207_5ad2_4fee_8cb9_f373175b3f99
#运行以下脚本,确保发送到已启用邮件的公用文件夹的所有电子邮件正确路由到 Exchange Online。该脚本将标记已启用邮件的公用文件夹,ExternalEmailAddress并指向对应的Exchange Online文件夹
.\SetMailPublicFolderExternalAddress.ps1 -ExecutionSummaryFile:mepf_summary.csv
Set-OrganizationConfig -PublicFolderMailboxesMigrationComplete:$true -PublicFoldersEnabled Remote
2. Exchange Online PowerShell中执行的步骤
提示:
1) 执行Complete-MigrationBatch PublicFolderMigration命令后,迁移批处理、迁移请求的状态并不会立即变为completing,而仍保持为synced 状态很长时间。在我最近的实验中,约6小时后才真正开始完成迁移的动作。
2) 步骤8中设置测试邮箱使用Exchange Online 的PF后,也需等待约30分钟后命令才生效,Outlook随后连接至Exchange Online的PF。
#Exchange online PowerShell 中执行
#连接至Exchange Online,提供有Exchange Online 管理员的帐户信息
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName ejoinadmin@ejoinclass.com
#步骤2 准备迁移
#确保没有现有的公用文件夹迁移请求
Get-MigrationBatch | ?{$_.MigrationType.ToString() -eq "PublicFolder"}
#看是否存在任何公用文件夹邮箱
Get-Mailbox -PublicFolder
#步骤 4:在 Exchange Online 中创建公用文件夹邮箱
$mappings = Import-Csv map.csv
$primaryMailboxName = ($mappings | Where-Object FolderPath -eq "\" ).TargetMailbox;
New-Mailbox -HoldForMigration:$true -PublicFolder -IsExcludedFromServingHierarchy:$false $primaryMailboxName
($mappings | Where-Object TargetMailbox -ne $primaryMailboxName).TargetMailbox | Sort-Object -unique | ForEach-Object { New-Mailbox -PublicFolder -IsExcludedFromServingHierarchy:$false $_ }
#步骤 5:启动迁移请求
#$Source_Credential是Exchange 2016 本地环境中管理员权限的用户的凭据
$Source_Credential = Get-Credential ejoin\ejadmin
#$Source_RemoteServer中 设置Exchange 2016 的EWS 服务的外部可访问到的FQDN
$Source_RemoteServer = "autodiscover.ejoinclass.com"
#创建公用文件夹迁移终结点和公用文件夹迁移请求
#bytes 后的文件需提供完整路径
$bytes = [System.IO.File]::ReadAllBytes('C:\PFScripts\map.csv')
$PfEndpoint = New-MigrationEndpoint -PublicFolder -Name PublicFolderEndpoint -RemoteServer $Source_RemoteServer -Credentials $Source_Credential
New-MigrationBatch -Name PublicFolderMigration -CSVData $bytes -SourceEndpoint $PfEndpoint.Identity -SourcePfPrimaryMailboxGuid f8032deb-7f29-49ed-bc61-ab503bf83c20 -NotificationEmails ejoinadmin@ejoinclass.com
#开始数据同步
Start-MigrationBatch PublicFolderMigration
#===============================Exchange Online 步骤, 完成PF 迁移,需预约服务中断时间=================================================
#连接至Exchange Online
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName ejoinadmin@ejoinclass.com
#步骤 6:锁定本地服务器上公用
#ExO 上确保迁移批处理和单个迁移请求已成功同步
Get-MigrationBatch |?{$_.MigrationType -like "*PublicFolder*"} | ft
Get-PublicFolderMailboxMigrationRequest | Get-PublicFolderMailboxMigrationRequestStatistics
#步骤7:完成公用文件夹迁移
#重新运行以下脚本,以确保任何启用邮件的公用文件夹与Exchange Online一致
.\Sync-ModernMailPublicFolders.ps1 -Credential (Get-Credential) -CsvSummaryFile:sync_summary.csv
Complete-MigrationBatch PublicFolderMigration
#步骤 8:测试和解锁 Exchange Online 中的公用文件夹
#Set-Mailbox -Identity <test user> -DefaultPublicFolderMailbox <public folder mailbox identity>
Set-Mailbox -Identity pingli -DefaultPublicFolderMailbox PFMBX1
#Outlook PF使用测试,确认测试用户的Outlook 公用文件夹连接是连到Exchange Online的,即outlook.office.com
#解锁 Exchange Online 中的公用文件夹,设置ExO 使用本地(ExO)的PF
Set-OrganizationConfig -RemotePublicFolderMailboxes $Null -PublicFoldersEnabled Local