使用附件时,Send-MailMessage 关闭每第二个连接

Jac*_*vin 3 email powershell smtp smtpclient

我正在尝试编写一个 powershell 脚本来向 30 人发送带有几个附件的电子邮件。电子邮件是个性化的,因此必须单独发送。该脚本在没有附件的情况下运行良好。但是,当使用附件时,Send-MailMessage 的每个其他实例都会失败,并显示:

Send-MailMessage : 无法将数据写入传输连接:远程主机强行关闭了现有连接。

在发送消息之间等待/暂停多长时间似乎并不重要。即使我等了几分钟,第一个实例总是会成功,下一个会失败,下一个会成功,等等。我什至注意到在运行脚本之间,我对偶数或奇数的 ctrl+c 决定了成功Send-MailMessage 的第一个实例。如果最后一条消息失败,则第一条消息成功,反之亦然。

我的代码非常简单,我们只有一个包含所有用户的数组,并且

$array | foreach {
  Write-Host "Sending Mail..."
  Send-MailMessage -From 'myemail@domain' -To $_.EmailAddress 
  -SmtpServer 'fqdn' 
  -Attachments "1.pdf", "2.pdf"
  -Subject 'Subject'
  -Body ($html)
  -BodyAsHtml
}
Run Code Online (Sandbox Code Playgroud)

因此,输出将类似于以下内容:

发送邮件...

发送邮件...

Send-MailMessage : 无法将数据写入传输连接:远程主机强行关闭了现有连接。

发送邮件...

发送邮件...

Send-MailMessage : 无法将数据写入传输连接:远程主机强行关闭了现有连接。

在没有错误的情况下,邮件会完好无损地到达。

我可以通过执行以下操作来“解决”这个问题:

try { Send-MailMessage ... -EA Stop }
catch { Send-MailMessage }
Run Code Online (Sandbox Code Playgroud)

结果,30/30 的人会收到邮件(而不是 15/30),因为每次尝试(除了 #1)都失败了,但是 catch 块中的代码总是能够成功。

当然,这不是一个真正的解决方案,我不想就这样离开它。有没有人对这里发生的事情有任何了解,以及如何解决它?

Jac*_*vin 5

我相信我已经找到了最好的解决方案。非常感谢 Matt 在评论中帮助我解决这个问题。

Send-Mailmessage一旦完成发送邮件,问题似乎是由于没有正确处理连接对象而产生的。Send-Mailmessage使用现有连接运行会强制处理它,因此第三次运行它会成功。

解决方法是将每个实例Send-Mailmessage作为单独的作业运行。要引用马特

PowerShell 作业有自己的内存和资源。工作完成后,应该删除内存。

因此,每次我们Send-Mailmessage作为作业运行时,都会正确创建和处理连接。我还通过管道将其Wait-Job | Receive-Job用于自然速率限制、查看输出并防止理论上可能存在的任何内存问题。

Start-Job -ScriptBlock {
  Send-MailMessage -From 'mymail' -To 'theirmail' -SmtpServer 'fqdn' -Attachments "$($args[0])\1.pdf", "$($args[0])\2.pdf" -Subject 'subject' -Body ("test")
} -ArgumentList $PSScriptRoot | Wait-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)

使用此方法不会产生错误,并且应该会减少 SMTP 服务器的负载。