【问题标题】:Powershell Send-MailMessage does not dispose attachment after failing to sendPowershell Send-MailMessage 发送失败后不处理附件
【发布时间】:2013-08-22 12:07:56
【问题描述】:

我的自动 Powershell Hyper-V 备份脚本有点问题。该脚本运行良好,但我的问题是,当我尝试发送带有日志文件作为附件的电子邮件时,它在发送失败后不会解锁文件。 (我无法检查它的行为,当它成功发送邮件时,但老实说,它也应该处理它,即使它发送失败。)

我已经在整个网络上进行了搜索,我所能找到的只是:

  1. Send-MailMessage 发送后自动处理附件 邮件。
  2. 将 Powershell v1 中的方法与 new-object 一起使用 system.net.mail.mailmessage 和新对象 system.net.mail.attachment。

这是我的代码的一部分(我已将其缩短为所需代码的基本要素):

[String]$ComputerName = Get-Content Env:ComputerName
[String]$LogFile = "Hyper-V Backup Logs\$ComputerName.Hyper-V Backup." + (Get-Date).Day + "-" +(Get-Date).Month + "-" +(Get-Date).Year + "-" +(Get-Date).Hour + "." +(Get-Date).Minute + "." +(Get-Date).Second + ".log"

"# $(Get-Date) :: Attempting to send log file to 'Support@example.dk'..." | Out-File $LogFile -Append
Try
{
    $EmailTo = "Support@example.dk"
    $EmailFrom = "Service@example.dk"
    $EmailServer = "server.example.dk"
    $EmailSubject = "An error occurred during Hyper-V Backup on $ComputerName!"
    $EmailBody = "Hello,

    An error occured during Hyper-V Backup on $ComputerName.

    I have attached the log file, $LogFile, to this mail.

    Kind Regards,<br></p>
    Hyper-V Backup.
    "

    Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -Attachments $LogFile -SmtpServer $EmailServer
    "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" | Out-File $LogFile -Append

}
Catch
{
    "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" | Out-File $LogFile -Append
    "                      :: Error Command: Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $EmailSubject -Body $EmailBody -Attachments $LogFile -SmtpServer $EmailServer" | Out-File $LogFile -Append
    "                      :: Error Message: $($_.Exception.Message)" | Out-File $LogFile -Append
}

这会引发以下错误:

Out-File : The process cannot access the file 'C:\Hyper-V Backup\Hyper-V Backup
Logs\example.Hyper-V Backup.22-8-2013-13.48.16.log' because it is being used by
another process.
At C:\Hyper-V Backup\Hyper-V Backup.ps1:310 char:163
+ ... port@example.dk" | Out-File $LogFile -Append
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (:) [Out-File], IOException
    + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

所以我的问题是,在发送电子邮件失败后,如何让 Send-MailMessage 处理附件,以便我的脚本可以继续写入日志文件?

PS。当邮件发送成功时,上面的脚本可以正常工作,不会引发任何错误,也不会锁定文件。

亲切的问候,

托马斯·施密特

编辑:

我改用旧的 Powershell v1 方式:

Try
{
    $SMTPServer = "exchange.example.dk"
    $SMTP = new-object Net.Mail.SmtpClient($SMTPServer)

    $EmailAttachment = new-object Net.Mail.Attachment($Logfile)
    $EmailMessage = new-object Net.Mail.MailMessage

    $EmailMessage.Attachments.Add($EmailAttachment)
    $EmailMessage.From = "service@example.dk"
    $EmailMessage.To.Add("spport@example.dk")
    $EmailMessage.Subject = "Notification from email server"
    $EmailMessage.Body = "Hello,
An error occurred during A/S Hyper-V Backup on $ComputerName.

I have attached the log file, $LogFile, to this mail.

Kind Regards,
Hyper-V Backup.
"
    $SMTP.Send($EmailMessage)
    $EmailAttachment.Dispose()
    Write-Host "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" -foregroundcolor green; "# $(Get-Date) :: Successfully send log file to 'Support@example.dk" | Out-File $LogFile -Append
}
Catch
{
    $EmailAttachment.Dispose()
    Write-Host "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" -foregroundcolor red; "# $(Get-Date) :: Failed to send log file to 'Support@example.dk" | Out-File $LogFile -Append
    "                      :: Error Command: SMTP.Send(EmailMessage)" | Out-File $LogFile -Append
    "                      :: Error Message: $($_.Exception.Message)" | Out-File $LogFile -Append
}

但如果有人可以提供上述问题的答案,我很乐意使用该解决方案!

亲切的问候,

托马斯·施密特

【问题讨论】:

    标签: email powershell dispose


    【解决方案1】:

    这就是我处理它的方式,它似乎对我有用:

     try {
        $ErrorActionPreference = 'Stop'
        $SmtpSettings = @{
            To = $Recipients.Split(',')
            From = $Sender
            SmtpServer = $SmtpServer
            Subject = "Email test"
            Body = "Please check attached file"
            Attachment = $Attachment
        }
        Send-MailMessage @SmtpSettings -BodyAsHtml
     } catch {
        $ErrorActionPreference = 'Continue'
        [gc]::collect()
        $CustomError = ($_ -replace "`r`n","")
        $ScriptLine = "$($_.InvocationInfo.ScriptLineNumber)" +','+ "$($_.InvocationInfo.OffsetInLine)"
        Write-Verbose "Error sending email: $CustomError (script line $ScriptLine)"
    }
    

    我基本上使用了垃圾收集器 - [gc]::collect(),尽管在​​发送电子邮件时出错,它还是解锁了附件文件。 我还在 try 中设置了 $ErrorActionPreference = 'Stop' 以便它可以正确捕获错误并在 $ErrorActionPreference = 'Continue' 内部catch 这样脚本就不会完全停止。

    【讨论】:

      【解决方案2】:

      试试这种老式风格。适合我。

      #Send Email
      $smtpServer = "10.10.10.10"
      $file = "C:\Temp\TEST.zip"
      $att = new-object Net.Mail.Attachment($file)
      $msg = new-object Net.Mail.MailMessage
      $smtp = new-object Net.Mail.SmtpClient($smtpServer)
      $msg.From = "MYNAME@DOMAIN.com"
      $msg.To.Add("yourname@domian.com")
      $msg.CC.Add("yourname2@domain.com")
      $msg.Subject = "Subject here"
      $msg.Body = "Body here"
      $msg.Attachments.Add($att)
      $smtp.Send($msg)
      $att.Dispose()
      

      【讨论】:

        猜你喜欢
        • 2012-03-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-18
        • 2012-05-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多