.NET 使用 SmtpClient 和 Mandrill SMTP 发送失败

.NET sending using SmtpClient with Mandrill SMTP fails

当以下代码中的 mailFromName 包含“æ”、“ø”或“å”时,通过 Mandrill SMTP 发送邮件静默失败时,我们遇到了一个难题。当我们使用另一个 SMTP 时,邮件发送得很好。

Mail.ReplyToList.Add(New MailAddress(mailFromAddress, mailFromName, System.Text.Encoding.UTF8))

我们使用 .NET smtpClient class。

Dim SmtpClient As New System.Net.Mail.SmtpClient
SmtpClient.Send(Mail)
SmtpClient.Dispose()

更新

正如评论中所建议的那样,我同意这看起来像是一个编码问题,但我看不出我能对此做些什么。

它似乎只连接到包含 æ、ø 和 å 的 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 Overview 中都可见,一切正常。

想看我的完整代码吗?

在这里,注意发送失败的邮件不会产生异常。

  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 activity 列表中的邮件通信的屏幕截图 - 即使我们收到 SMTP 响应正常且已排队 ID。

我举三个例子:

已交付:

mailFromName = "xxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxxxx"

未交付:

mailFromName = "xxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxæxx"

已交付:

mailFromName = "æxx xxxxxxxxx xxxx - xxxxxxxxxx xxxxxxx xxxxxxxxx"

我相信我已经找到了对此的解释。似乎 smtpclient 在主题和回复显示名称的大约 72 个字符之后添加了一个新行。问题是这似乎发生在字符串被编码之后。因此,在某些情况下,在编码字符的中间添加换行符,这在我看来是非法的。

我不确定为什么 Mandrill SMTP 服务器失败而没有返回错误,而其他 SMTP 服务器可以很好地处理这种情况。

现在我明白发生了什么,我必须想办法解决它 - 最好的建议会得到赏金。