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

无需解压ZIP,用PowerShell解析EML文件From与To字段的问题

解决方案

错误原因

你遇到的问题是ADODB.Stream.LoadFromFile()方法仅支持本地文件路径,而你传入的是ZipArchiveEntry对象(对应压缩包内的文件流),所以触发类型不匹配错误。

方案1:修复CDO.Message的流处理逻辑

无需将文件解压到本地,直接把ZipEntry的流复制到ADODB Stream中,再交给CDO.Message解析:

$zipPath = "你的ZIP文件路径"
$zipArchive = [IO.Compression.ZipFile]::OpenRead($zipPath)

foreach ($entry in $zipArchive.Entries) {
    # 只处理EML文件
    if (-not $entry.Name.EndsWith(".eml", [StringComparison]::OrdinalIgnoreCase)) {
        continue
    }

    # 读取ZipEntry的流
    $zipStream = $entry.Open()
    
    # 初始化ADODB Stream并写入Zip流内容
    $adoStream = New-Object -ComObject ADODB.Stream
    $adoStream.Type = 1 # adTypeBinary
    $adoStream.Open()
    
    # 将.NET流转换为字节数组,再写入ADODB Stream
    $buffer = New-Object byte[] 4096
    while (($readBytes = $zipStream.Read($buffer, 0, $buffer.Length)) -gt 0) {
        $adoStream.Write($buffer, 0, $readBytes)
    }
    $adoStream.Position = 0 # 重置流指针到开头

    # 用CDO.Message解析EML
    $cdoMsg = New-Object -ComObject CDO.Message
    $cdoMsg.DataSource.OpenObject($adoStream, "_Stream")

    # 提取From和To邮箱
    [PSCustomObject]@{
        FileName = $entry.Name
        From     = $cdoMsg.From
        To       = $cdoMsg.To
    }

    # 清理资源
    $cdoMsg | Remove-Variable
    $adoStream.Close()
    $zipStream.Close()
}

$zipArchive.Dispose()

方案2:使用.NET原生类解析(推荐,无需COM对象)

用System.Net.Mail.MailMessage类直接读取Zip流,避免依赖COM组件,兼容性更好:

$zipPath = "你的ZIP文件路径"
$zipArchive = [IO.Compression.ZipFile]::OpenRead($zipPath)

foreach ($entry in $zipArchive.Entries) {
    if (-not $entry.Name.EndsWith(".eml", [StringComparison]::OrdinalIgnoreCase)) {
        continue
    }

    try {
        # 直接从Zip流创建MailMessage
        $zipStream = $entry.Open()
        $mailMsg = [System.Net.Mail.MailMessage]::new($zipStream)

        # 提取邮箱信息(MailMessage的From/To是MailAddress对象,可直接取Address属性)
        [PSCustomObject]@{
            FileName = $entry.Name
            From     = $mailMsg.From.Address
            To       = $mailMsg.To | ForEach-Object { $_.Address } -join ", "
        }
    }
    catch {
        Write-Warning "解析文件 $($entry.Name) 失败: $_"
    }
    finally {
        $zipStream.Close()
        if ($mailMsg) { $mailMsg.Dispose() }
    }
}

$zipArchive.Dispose()

注意事项

  • 方案2中,.NET Core/.NET 5+环境下System.Net.Mail.MailMessage已被标记为过时,可改用System.Net.Mime.MailMessage(需确认PowerShell版本对应的.NET环境)。
  • 处理大文件时,两种方案都是流处理,不会占用过多内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:45:37