.NET 使用 SmtpClient 和 Mandrill SMTP 发送失败
Posted
技术标签:
【中文标题】.NET 使用 SmtpClient 和 Mandrill SMTP 发送失败【英文标题】:.NET sending using SmtpClient with Mandrill SMTP fails 【发布时间】:2017-10-19 17:40:31 【问题描述】:当以下代码中的 mailFromName 包含“æ”、“ø”或“å”时,我们正面临通过 Mandrill SMTP 发送邮件静默失败的难题。当我们使用另一个 SMTP 时,邮件发送得非常好。
Mail.ReplyToList.Add(New MailAddress(mailFromAddress, mailFromName, System.Text.Encoding.UTF8))
我们使用 .NET smtpClient 类。
Dim SmtpClient As New System.Net.Mail.SmtpClient
SmtpClient.Send(Mail)
SmtpClient.Dispose()
更新
正如 cmets 中所建议的,我同意这看起来像是一个编码问题,但在我们这边看不到我能做些什么。
它似乎只连接到包含 æ、ø 和 å 的 RepleyToList 而不是 Mail.To
,我以类似的方式定义如下:
Dim mTo As New MailAddress(mailToAddress, mailToName, System.Text.Encoding.UTF8)
Mail.To.Add(mTo)
mailToName
可以包含 æ、ø 和 å 并且发送完全没问题。
很难证明某事没有发生,但我确定邮件没有发送,并且我确定它与replyToList 中的发件人名称相关联。
我怎么知道?
我在发送之前记录邮件。包含相关字符的邮件会被记录,但在 https://mandrillapp.com/activity 中永远不会显示,并且永远不会到达收件人。我删除了 æ、ø 或 å - 在 Mandrill 概述中都可以看到并且一切正常。
想看我的完整代码吗?
在这里,注意发送失败的邮件不会产生异常。
Public Sub sendMail(ByVal mailFromAddress As String, ByVal mailFromName As String, _
ByVal mailToAddress As String, ByVal mailToName As String, ByVal mailCcAddress As String, ByVal mailBCcAddress As String, _
ByVal mailPriority As Net.Mail.MailPriority, ByVal IsBodyhtml As Boolean, ByVal mailSubject As String, _
ByVal bodyPlain As String, ByVal bodyHTML As String)
Const maxtry As Integer = 3
Dim tries As Integer = 0
Dim failed As Boolean = False
' mailFromName = mailFromName.Replace("æ", "ae")
Do
tries += 1
Try
failed = False
Dim Mail As New MailMessage
If mailFromAddress <> String.Empty Then
'Mail.ReplyTo = New MailAddress(mailFromAddress, mailFromName, System.Text.Encoding.UTF8)
Mail.ReplyToList.Add(New MailAddress(mailFromAddress, mailFromName, System.Text.Encoding.UTF8))
Else
'Mail.ReplyTo = New MailAddress(Me.MailAddressFrom, Me.MailAddressDisplayName, System.Text.Encoding.UTF8)
Mail.ReplyToList.Add(New MailAddress(Me.MailAddressFrom, Me.MailAddressDisplayName, System.Text.Encoding.UTF8))
End If
Mail.From = New MailAddress(Me.MailAddressFrom, Me.MailAddressDisplayName, System.Text.Encoding.UTF8)
Mail.Sender = New MailAddress(Me.MailAddressFrom, Me.MailAddressDisplayName, System.Text.Encoding.UTF8)
If mailToAddress <> String.Empty Then
Dim mTo As New MailAddress(mailToAddress, mailToName, System.Text.Encoding.UTF8) 'UTF8
Mail.To.Add(mTo)
End If
If mailCcAddress <> String.Empty Then
Dim mCc As New MailAddress(mailCcAddress)
Mail.CC.Add(mCc)
End If
If mailBCcAddress <> String.Empty Then
Dim mBCc As New MailAddress(mailBCcAddress)
Mail.Bcc.Add(mBCc)
End If
Mail.Priority = mailPriority
Mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
Mail.IsBodyHtml = IsBodyHtml
Mail.HeadersEncoding = Encoding.GetEncoding("utf-8")
Mail.Subject = mailSubject
Mail.SubjectEncoding = Encoding.GetEncoding("utf-8") ' = System.Text.Encoding.Default 'UTF8 'Default ' Test on all possible encodings
If IsBodyHtml Then
Mail.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(bodyHTML, System.Text.Encoding.Default, "text/html"))
End If
Mail.BodyEncoding = Encoding.GetEncoding("utf-8")
Mail.Body = bodyPlain
' Add to log
addToMailLog(mailToAddress, mailCcAddress, mailSubject, bodyPlain)
' Send
Dim SmtpClient As New System.Net.Mail.SmtpClient
'SmtpClient.ServicePoint.MaxIdleTime = 1
SmtpClient.Send(Mail)
Me._status = EMailStatus.EOkay
SmtpClient.Dispose()
Catch ex As Exception
Dim debugInfo As New CDebug("sendMail", "Try: " & tries.ToString & ", UserId: " & Me.UserId, ex.ToString, Me.UserId, String.Empty)
Me._status = EMailStatus.EMailSendError
failed = True
End Try
Loop Until (failed = False Or tries >= maxtry)
End Sub
更新二
我现在已经使用 WireShark 跟踪了 SMTP 通信。请参阅屏幕截图,该屏幕截图显示了未传递且未显示在 Mandrill 活动列表中的邮件的通信 - 即使我们得到 SMTP 响应正常和排队 ID。
我举了三个例子:
已交付:
mailFromName = "xxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxxxx"
未送达:
mailFromName = "xxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxæxx"
已交付:
mailFromName = "æxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxxxx"
【问题讨论】:
似乎很明显这是一个编码问题。至少通过this Q+A 工作。如果这没有帮助,请具体说明您如何知道地址被拒绝。 感谢您的评论,我查看了您的链接,但与我们的问题没有真正的联系 - 请参阅我更新的问题了解更多详细信息。SmtpClient
上有一个名为 DeliveryFormat
的设置。如果将其设置为“国际”会发生什么? SmtpClient.DeliveryFormat = SmtpDeliveryFormat.International
谢谢 - 不幸的是 DeliveryFormat 是在 .NET 4.5 框架中引入的,而我们使用 4.0
您至少可以使用 .NET 4.5 进行测试吗?据我所知,以前版本中的 SmtpClient 并不支持所有国际字符的情况。如果您在 .NET 4.5 中仍然遇到此问题,我们至少可以排除一个潜在原因。
【参考方案1】:
我相信我已经找到了对此的解释。似乎 smtpclient 在主题和回复显示名称的大约 72 个字符之后添加了一个新行。问题是这似乎发生在字符串被编码之后。因此,在某些情况下,在编码字符的中间添加了一个换行符,这 afaik 是非法的。
我不知道为什么 Mandrill SMTP 服务器失败但没有返回错误,而其他 SMTP 服务器处理得很好。
现在我了解了正在发生的事情,我必须想办法解决它 - 最好的建议会得到赏金。
【讨论】:
您实施过解决方案吗?我相信我遇到了这个问题 没有,从未找到解决方案 - 最终使用了对我们来说足够的西方编码 谢谢,最后我们转向了 MailKit以上是关于.NET 使用 SmtpClient 和 Mandrill SMTP 发送失败的主要内容,如果未能解决你的问题,请参考以下文章
将“SmtpClient.EnableSsl”设置为 true 时,“System.Net.Mail.SmtpClient”需要哪些端口?
使用 SmtpClient 和 MailMessage 时如何禁止电子邮件验证
如何使用 POP3 和 SmtpClient 转发多部分 MIME 电子邮件?
.NET SmtpClient 在使用密件抄送时暴露 10 个电子邮件地址(通过 Mandrill)