You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决提取大邮箱多元数据时的HRESULT操作停止错误?

大型Outlook邮箱元数据提取PowerShell脚本HRESULT错误问题

问题现象

  • 应用于小型邮箱(约9000封邮件)时可正常运行;
  • 应用于大型邮箱(约25万封邮件)且仅提取单个元数据字段时也可正常运行;
  • 应用于大型邮箱且提取多个元数据字段时,会输出以下HRESULT错误,仅捕获33146封邮件,生成不完整的表格:
Exception from HRESULT: 0xB5940115
At C:\file\path\path\name.ps1:15 char:18
+     foreach ($item in ($folder |Select-Object -ExpandProperty "I ...
+
     + CategoryInfo     :OperationStopped: (:) [], COMException
     + FullyQualifiedErrorID: System.Runtime.InteropServices.COMException

Exception from HRESULT: 0xBBC40115
At C:\file\path\path\name.ps1:13 char:14
+    foreach ($folder in $ParentFolder.Folders)
+
     + CategoryInfo     :OperationStopped: (:) [], COMException
     + FullyQualifiedErrorID: System.Runtime.InteropServices.COMException

Exception from HRESULT: 0xBFE40115
At C:\file\path\path\name.ps1:13 char:14
+     foreach ($folder in $ParentFolder.Folders)
+
     + CategoryInfo     :OperationStopped: (:) [], COMException
     + FullyQualifiedErrorID: System.Runtime.InteropServices.COMException

已尝试的解决方法

  • 搜索错误码,未找到相关结果;
  • 搜索FullyQualifiedErrorID,未找到相关结果;
  • 使用DataTable、提取EntryID结合单字段、按1000封分批处理、静默跳过错误,均未解决;
  • 最新尝试按文件夹大小处理(小于1000封直接导出,大于1000封分批导出),但无CSV输出,不确定原因。

初始完整脚本

function Get-MailFromOutlookFolder
{
    [CmdletBinding()]
    param 
    (
        [Parameter(Mandatory = $true)]
        [Object] $ParentFolder
    )

    $items = @()

    foreach ($folder in $ParentFolder.Folders)
    {
        foreach ($item in ($folder | Select-Object -ExpandProperty "Items"))
        { 
            if ($item.Class -eq 43)
            {
                # process email
                $PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
                #$smtpAddress = $item.PropertyAccessor.GetProperty($PR_SMTP_ADDRESS)
                $items += $item | Select-Object -Property "ConversationTopic", "ReceivedTime", "SenderName", "ReceivedByName", "BCC", "CC","Size", "SenderEmailAddress", @{ "Label" = "Folder"; "Expression" = { $_.Parent.Name } }, @{name="Attachments";expression={$_.Attachments|%{$_.DisplayName}}}
            }
        }

        # process (sub)folder items
        $items += Get-MailFromOutlookFolder -ParentFolder $folder
    }

    return $items    
}

$outlook     = New-Object -Com "Outlook.Application"
$mapi        = $outlook.GetNamespace("MAPI")
$recipient = $mapi.CreateRecipient("name@domain.ca")
$folder = $mapi.GetSharedDefaultFolder($recipient, [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$folder1 = $folder.parent.folders('Online Archive - name@domain.ca')
$results = Get-MailFromOutlookFolder -ParentFolder $folder1
$results | Export-Csv -Path "C:\Fakefolder\email_account_name_2025-06-20.csv"

更新尝试的脚本

$table = New-Object System.Data.DataTable
$table.Columns.Add("EntryID", [System.String])
#$table.Columns.Add("ReceivedTime", [System.DateTime])
$table.Columns.Add("AttachmentNames", [System.String])
#$table.Columns.Add("Body", [System.String])


function Get-MailFromOutlookFolder
{
    [CmdletBinding()]
    param 
    (
        [Parameter(Mandatory = $true)]
        [Object] $ParentFolder
    )


  foreach ($folder in $ParentFolder.Folders) {
        foreach ($item in ($folder | Select-Object -ExpandProperty "Items")) {
            if ($item.Class -eq 43) {
                $attachments = @()
                foreach ($att in $item.Attachments) {
                    $attachments += $att.FileName
                }
                # Clean and truncate Body field
                #$body = $mail.Body -replace "(`r`n|`n|`r)", " "
                #$maxLength = 32000
                #if ($body.Length -gt $maxLength) {
                #    $body = $body.Substring(0, $maxLength)
                #}
                $row = $table.NewRow()
                $row["EntryID"]   = $item.EntryID
                $row["AttachmentNames"] = ($attachments -join "; ")
                #$row["Body"]   = $item.EntryID
                #if ($mail.ReceivedTime) {
                #        $row["ReceivedTime"] = $mail.ReceivedTime
                #    } else {
                #        $row["ReceivedTime"] = [DBNull]::Value
                #    }
                $table.Rows.Add($row)
            }
        }

}



$outlook     = New-Object -Com "Outlook.Application"
$mapi        = $outlook.GetNamespace("MAPI")
$recipient = $mapi.CreateRecipient("fake@fake.ca")
$folder = $mapi.GetSharedDefaultFolder($recipient, [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$folder1 = $folder.parent.folders('Online Archive - fake@fake.ca')
$results = Get-MailFromOutlookFolder -ParentFolder $folder1
$results | Export-Csv -Path "C:\fake\fake_2025-07-04.csv"

2025-07-21更新

制作了带计数器的脚本,每处理1000封就导出并清空DataTable,该方法有效但存在问题:邮件数少于1000的文件夹会被跳过,如8001封的文件夹会遗漏第8001封。

后续尝试按文件夹邮件数处理的脚本如下,但无CSV输出:

$ErrorActionPreference = 'SilentlyContinue'

#Make table with appropriate columns
$table = New-Object System.Data.DataTable
$table.Columns.Add("EntryID", [System.String])
$table.Columns.Add("AttachmentNames", [System.String])
$table.Columns.Add("Body", [System.String])
$table.Columns.Add("ConversationTopic", [System.String])

#make counters and empty hashtable
$counter = 0
$counter2 = 0
$myDictionary = @{}

#Get a hashtable listing folder name as keys and total items as values
function Get-MailFromOutlookFolder
{
    [CmdletBinding()]
    param 
    (
        [Parameter(Mandatory = $true)]
        [Object] $ParentFolder
    )

    foreach ($folder in $ParentFolder.Folders) {
        $counter = 0
        foreach ($item in ($folder | Select-Object -ExpandProperty "Items")) {
            $counter++}
        $key = $folder.FolderPath
        $value = $counter
        $myDictionary[$key] = $value
        }
}

#Run Hashtable so that folders are processed in groups of 1000
function Traverse-NestedHashtable {
   param (
        [Parameter(Mandatory=$true)]
        [Hashtable]$myDictionary,
        [Object] $ParentFolder
    )
   foreach ($key in myDictionary) {
   #Process folders with less than 1000 items
        if ($counter -lt 1000) {
            $folder = $key
            foreach ($item in ($folder | Select-Object -ExpandProperty "Items")) {
                    if ($item.Class -eq 43) {
                        $attachments = @()
                        foreach ($att in $item.Attachments) {
                            $attachments += $att.FileName
                        }
                        # Clean and truncate Body field
                        $body = $mail.Body -replace "(`r`n|`n|`r)", " "
                        $maxLength = 32000
                        if ($body.Length -gt $maxLength) {
                            $body = $body.Substring(0, $maxLength)
                        }
                        $row = $table.NewRow()
                        $row["EntryID"]   = $item.EntryID
                        $row["AttachmentNames"] = ($attachments -join "; ")
                        $row["Body"]   = $item.Body
                        $row["ConversationTopic"]   = $item.ConversationTopic
                        $table.Rows.Add($row)
                        $folderSafe = $folder.FolderPath -replace '[\\/:*?"<>|]', '_' 
                        $counterString = $counter.ToString()
                        $filePath = "C:\foo\" + $folderSafe + "_" + $counterString + ".csv"
                        $table | Export-Csv -Path "$filePath" -notypeinformation
                        $table.Clear()}}}
#Process folders with more than 1000 items
           if ($counter -gt 1000) {
                $folder = $key
                foreach ($item in ($folder | Select-Object -ExpandProperty "Items")) {
                    $counter2++
                    if ($item.Class -eq 43) {
                        $attachments = @()
                        foreach ($att in $item.Attachments) {
                            $attachments += $att.FileName
                        }
                        # Clean and truncate Body field
                        $body = $mail.Body -replace "(`r`n|`n|`r)", " "
                        $maxLength = 32000
                        if ($body.Length -gt $maxLength) {
                            $body = $body.Substring(0, $maxLength)
                        }
                        $row = $table.NewRow()
                        $row["EntryID"]   = $item.EntryID
                        $row["AttachmentNames"] = ($attachments -join "; ")
                        $row["Body"]   = $item.Body
                        $row["ConversationTopic"]   = $item.ConversationTopic
                        $table.Rows.Add($row)
                        $folderSafe = $folder.FolderPath -replace '[\\/:*?"<>|]', '_' 
#When number of items is 1000 exactly, send the collected items in the datatable to spreadsheet
                        if ($counter2 % 1000 -eq 0) {
                            $counterString = $counter.ToString()
                            $filePath = "C:\foo\" + $folderSafe + "_" + $counterString + ".csv"
                            $table | Export-Csv -Path "$filePath" -notypeinformation
                            $table.Clear()}
#When number of items is the number in the folder exactly, send the collected items in the datatable to spreadsheet
                        if (($counter2 - $counter) % $counter -eq 0) {
                            $counterString = $counter.ToString()
                            $filePath = "C:\foo\" + $folderSafe + "_" + $counterString + ".csv"
                            $table | Export-Csv -Path "$filePath" -notypeinformation
                            $table.Clear()}
                        }}}}}


$outlook     = New-Object -Com "Outlook.Application"
$mapi        = $outlook.GetNamespace("MAPI")
$recipient = $mapi.CreateRecipient("foo@foo.ca")
$folder = $mapi.GetSharedDefaultFolder($recipient, [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox).Parent
$folder1 = $folder.parent.folders('Online Archive - foo@foo.ca')
Get-MailFromOutlookFolder -ParentFolder $folder1
Traverse-NestedHashtable -myDictionary -ParentFolder $folder1

内容的提问来源于stack exchange,提问作者oymonk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 19:37:03