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

在PowerShell中纯内存创建Zip并邮件发送的问题排查

PowerShell纯内存创建Zip并作为邮件附件发送问题修复

问题1:无法向Zip条目写入内容

你的代码有两个核心问题导致写入失败:

  • 仅关闭了StreamWriter,未关闭ZipArchive——ZipArchive必须明确关闭才能完成压缩条目写入,否则内存中的Zip结构不完整
  • StreamWriter未强制刷新缓冲区,可能导致内容未全部写入条目流

修复方式:

  • 用using块自动管理StreamWriter和ZipArchive的生命周期,自动完成释放/关闭操作,避免手动遗漏
  • 或手动调用StreamWriter.Flush()后关闭,再确保关闭ZipArchive

问题2:Zip作为邮件附件的流处理

要在流关闭后保留内容用于附件,关键注意:

  • 关闭ZipArchive后,需将MemoryStream的位置重置到开头(Seek(0, 0)),否则邮件读取流时会从末尾开始,无法获取内容
  • 创建Attachment时必须指定附件文件名(如"log.zip"),否则收件端无法识别文件类型
  • 确保MemoryStream在邮件发送完成前不被释放,可通过using块或保持引用实现

完整修正代码

$strTextToZip = '<html><head><title>Log report</title></head><body><p>Paragraph</p><ul><li>first</li><li>second</li></ul></body></html>'

# 加载所需程序集
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Net.Mail

# 替换为你的SMTP配置
$smtp = @{
    from    = "sender@example.com"
    to      = "recipient@example.com"
    subject = "日志报告压缩包"
    body    = "请查收附件中的日志报告"
    server  = "smtp.example.com"
}

# --- 创建内存流并处理Zip压缩 ---
$memoryStream = New-Object System.IO.MemoryStream
try {
    # 用using块自动管理ZipArchive,确保关闭时完成压缩
    using ($zipArchive = New-Object System.IO.Compression.ZipArchive($memoryStream, [System.IO.Compression.ZipArchiveMode]::Create, $true)) {
        # 创建Zip条目,指定压缩级别
        $htmlEntry = $zipArchive.CreateEntry("log.html", [System.IO.Compression.CompressionLevel]::Optimal)
        
        # 写入内容到Zip条目
        using ($entryStream = $htmlEntry.Open()) {
            using ($streamWriter = New-Object System.IO.StreamWriter($entryStream, [System.Text.Encoding]::UTF8)) {
                $streamWriter.Write($strTextToZip)
                $streamWriter.Flush() # 显式刷新确保内容全部写入
            }
        }
    }

    # --- 关键:重置内存流位置到开头 ---
    $memoryStream.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null

    # --- 创建并发送邮件 ---
    using ($msg = New-Object System.Net.Mail.MailMessage($smtp['from'], $smtp['to'], $smtp['subject'], $smtp['body'])) {
        $msg.IsBodyHTML = $true

        # 添加Zip附件,指定文件名和MIME类型
        $attachment = New-Object System.Net.Mail.Attachment($memoryStream, "log.zip", "application/zip")
        $msg.Attachments.Add($attachment)

        # 发送邮件(如需认证,取消注释下面两行)
        using ($smtpClient = New-Object System.Net.Mail.SmtpClient($smtp['server'])) {
            # $smtpClient.Credentials = New-Object System.Net.NetworkCredential("你的用户名", "你的密码")
            # $smtpClient.EnableSsl = $true
            $smtpClient.Send($msg)
        }
    }
} finally {
    # 释放内存流资源
    $memoryStream.Dispose()
}

关键修复点说明

  1. ZipArchive生命周期管理:用using块包裹ZipArchive,确保其正确关闭,完成压缩数据的最终写入
  2. 流位置重置:关闭ZipArchive后必须重置MemoryStream位置,否则邮件客户端无法读取到压缩内容
  3. 附件参数规范:指定附件文件名和MIME类型,保证收件端能正确识别并打开压缩包
  4. 自动资源释放:所有流、邮件对象均用using块管理,避免内存泄漏和资源未释放问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:05:26