PowerShell脚本提取Exchange Online邮箱全部附件失败寻求解决方案
提取Exchange Online邮箱指定类型附件的解决方案
问题背景
我不是PowerShell程序员/专家,缺乏脚本编写经验,现在需要解决一个问题:编写脚本提取Exchange Online邮箱的所有附件(仅图片、PDF、Word及Excel文件)。已经用Exchange Online管理模块连接了租户,写了一段脚本,执行无报错,能创建本地文件夹,但没提取到任何附件。另外不能使用Microsoft Purview合规门户的内容搜索功能,因为最终要把文件上传到SharePoint供数百位非技术用户访问,邮箱里有30多年的历史数据,求除内容搜索外的解决方案。
原脚本(无效)
#Scope to Mailbox $Mailbox = "someemail@somedomain.com" #Assign attachment location $OutputFolder = "$env:USERPROFILE\Downloads\Mailbox Attachment Results" #Create folder if doesn't exist if (-not (Test-Path -Path $OutputFolder)) { New-Item -ItemType Directory -Path $OutputFolder | Out-Null } #Get attachments $Attachments = Get-MailboxFolderStatistics -Identity $Mailbox -FolderScope All -IncludeOldestAndNewestItems | ForEach-Object { $Folder = $_.FolderPath.Replace("/", "\") $Permissions = Get-MailboxFolderPermission -Identity $Mailbox -User "Default" | Where-Object { $_.AccessRights -like "*CreateItems*" } if ($Permissions) { $Permissions | ForEach-Object { $FolderPermission = $_ Get-MailboxFolderStatistics -Identity $Mailbox -FolderScope All -IncludeOldestAndNewestItems -Folder $_.FolderPath | Where-Object { $_.FolderPath -eq $FolderPermission.FolderPath } | ForEach-Object { $_.Folder.Attachments | ForEach-Object { $Attachment = $_ $AttachmentPath = Join-Path -Path $OutputFolder -ChildPath ($Attachment.Name) $Attachment.Content | ForEach-Object { $_.Stream.Position = 0 $FileStream = [System.IO.File]::Create($AttachmentPath) $_.Stream.CopyTo($FileStream) $FileStream.Close() } } } } } }
原脚本问题分析
Get-MailboxFolderStatistics仅返回文件夹的统计信息(如项目数、大小),不包含邮件或附件的具体内容,所以无法通过它获取附件。- 权限判断逻辑完全错误:检查Default用户的
CreateItems权限和提取附件无关,只要当前连接的账号有该邮箱的读取权限即可。 - 重复调用
Get-MailboxFolderStatistics属于无效操作,没有实际作用。
正确解决方案脚本
# 目标邮箱地址 $Mailbox = "someemail@somedomain.com" # 附件保存路径 $OutputFolder = "$env:USERPROFILE\Downloads\Mailbox Attachment Results" # 需要提取的附件扩展名(不区分大小写) $AllowedExtensions = @(".jpg", ".jpeg", ".png", ".gif", ".pdf", ".docx", ".doc", ".xlsx", ".xls") # 创建输出文件夹(不存在则创建) if (-not (Test-Path -Path $OutputFolder)) { New-Item -ItemType Directory -Path $OutputFolder | Out-Null } # 获取邮箱所有文件夹的ID $Folders = Get-EXOMailboxFolderStatistics -Identity $Mailbox -FolderScope All | Select-Object -ExpandProperty FolderId # 遍历每个文件夹,获取邮件并提取附件 foreach ($FolderId in $Folders) { try { # 获取当前文件夹中的所有邮件(分批获取,避免超时) $Messages = Get-EXOMessage -Mailbox $Mailbox -FolderId $FolderId -PageSize 100 -All foreach ($Message in $Messages) { # 仅处理有附件的邮件 if ($Message.HasAttachments) { foreach ($Attachment in $Message.Attachments) { # 跳过内嵌附件(如邮件签名图片) if (-not $Attachment.IsInline) { # 检查附件扩展名是否在允许列表中(不区分大小写) $FileExt = [System.IO.Path]::GetExtension($Attachment.Name).ToLower() if ($AllowedExtensions -contains $FileExt) { # 处理重复文件名:如果文件已存在,添加序号 $AttachmentPath = Join-Path -Path $OutputFolder -ChildPath $Attachment.Name $Counter = 1 while (Test-Path -Path $AttachmentPath) { $FileNameWithoutExt = [System.IO.Path]::GetFileNameWithoutExtension($Attachment.Name) $AttachmentPath = Join-Path -Path $OutputFolder -ChildPath "$FileNameWithoutExt ($Counter)$FileExt" $Counter++ } # 保存附件到本地 $Attachment.Content | Set-Content -Path $AttachmentPath -Encoding Byte Write-Host "已保存附件: $AttachmentPath" } } } } } } catch { Write-Warning "处理文件夹 $FolderId 时出错: $_" continue } } Write-Host "附件提取完成,所有文件已保存到: $OutputFolder"
注意事项
- 权限要求:当前连接Exchange Online的账号需要拥有目标邮箱的
Full Access权限,或者至少有Read and Manage权限。 - 模块要求:确保已安装最新版的Exchange Online管理模块,可通过
Install-Module -Name ExchangeOnlineManagement安装。 - 大邮箱处理:脚本使用
-PageSize 100分批获取邮件,避免因单次请求数据量过大导致超时;如果邮箱数据量极大,可考虑添加日期筛选(如-ReceivedAfter参数)分阶段提取。 - 内嵌附件过滤:脚本跳过了内嵌附件(如邮件签名里的图片),如果需要提取这类附件,可删除
if (-not $Attachment.IsInline)判断。 - 重复文件处理:脚本会自动给重复文件名添加序号(如
report.pdf→report (1).pdf),避免覆盖已有文件。
内容的提问来源于stack exchange,提问作者Julez
相关产品推荐
相关产品推荐

