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

PowerShell中SaveToFile保存EML的PDF附件丢失扩展名问题求助

问题分析与修复方案

你的代码丢失PDF扩展名的核心问题有两个:

  • 遍历附件时,错误地从附件集合($CdoMessage.Attachments)而非当前单个附件($attachment)获取文件名
  • 未处理邮件主题中的非法字符,可能导致文件名异常或保存失败

修复后的代码

# 一次性获取所有eml文件,避免重复遍历目录
$emlFiles = Get-ChildItem -Path C:\Extract -Filter *.eml -Recurse -File

foreach ($emlFile in $emlFiles) {
    $adoDbStream = New-Object -ComObject ADODB.Stream
    $adoDbStream.Open()
    $adoDbStream.LoadFromFile($emlFile.FullName)
    
    $cdoMessage = New-Object -ComObject CDO.Message
    $cdoMessage.DataSource.OpenObject($adoDbStream, "_Stream")
    
    # 清理主题中的Windows非法文件名字符
    $cleanSubject = $cdoMessage.Subject -replace '[<>:"/\\|?*]', '_'
    
    foreach ($attachment in $cdoMessage.Attachments) {
        # 从当前附件对象获取完整文件名(含扩展名)
        $filename = $attachment.Filename
        
        # 仅处理PDF附件(按需保留此过滤逻辑)
        if ($filename -like '*.pdf') {
            $attFilename = "$cleanSubject-$filename"
            Write-Output $attFilename
            
            $savePath = Join-Path -Path C:\Extract -ChildPath $attFilename
            $attachment.SaveToFile($savePath)
        }
    }
    
    $adoDbStream.Close()
    # 释放COM对象,避免内存泄漏
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($adoDbStream) | Out-Null
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($cdoMessage) | Out-Null
}

关键修改说明

  • 优化文件遍历:原代码两次执行相同的Get-ChildItem,改为一次获取所有eml文件,提升运行效率
  • 修正文件名获取逻辑:将$CdoMessage.Attachments.Filename改为$attachment.Filename,确保拿到当前附件的完整文件名(包含扩展名)
  • 清理非法字符:邮件主题常包含<>:\"/\\|?*等Windows禁止的文件名字符,用-replace替换为下划线,避免保存失败
  • 新增PDF过滤:添加if ($filename -like '*.pdf')确保只处理PDF附件,减少无效操作
  • 释放COM对象:添加ReleaseComObject释放ADODB和CDO的COM对象,防止长期运行导致内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:07:29