无法使用斯堪的纳维亚字符向地址发送电子邮件

时间:2016-02-02 16:43:08

标签: c# .net email .net-4.5 smtpclient

使用SmtpClientMailMessageMailAddress课程,我无法发送电子邮件地址,例如åbc.def@domain.se。我得到错误/异常,如下所示:

  

在邮件标题中找到了无效字符:'å'。

     

---------------------------发送电子邮件时出错   --------------------------- System.Net.Mail.SmtpException:客户端或服务器仅配置为使用ASCII的电子邮件地址   local-parts:åbc.def@ domain.se。

     

at System.Net.Mail.MailAddress.GetUser(Boolean allowUnicode)

     

at System.Net.Mail.MailAddress.GetAddress(Boolean allowUnicode)

     

在System.Net.Mail.MailAddress.Encode(Int32 charsConsumed,Boolean   allowUnicode)

     

在System.Net.Mail.MailAddressCollection.Encode(Int32   charsConsumed,Boolean allowUnicode)      在System.Net.Mail.Message.PrepareHeaders(Boolean sendEnvelope,   Boolean allowUnicode)      在System.Net.Mail.Message.Send(BaseWriter writer,Boolean   sendEnvelope,Boolean allowUnicode)      在System.Net.Mail.SmtpClient.Send(MailMessage消息)

我的主题/正文中的这些字符很好,但不在电子邮件地址中。

我已尝试设置SmtpClient.DeliveryMethod = SmtpDeliveryFormat.InternationalMailMessage.HeadersEncoding = Encoding.Unicode(或UTF8),但似乎没有任何改变。这些是我们需要与之沟通的人的真实电子邮件地址,因此这有点问题。

我一直在挖掘.Net源代码,但并没有真正得到任何东西。我追踪了一个ServerSupportsEai属性,谷歌告诉我EAI代表电子邮件地址国际化(https://tools.ietf.org/html/rfc5336),但我不清楚这是否是我的代码中的限制,或者我正在谈论的特定服务器只是不支持这个...因为我正在使用测试服务器来避免向毫无戒心的瑞典人发送电子邮件!

有人可以帮助我清除这一点 - .Net是否支持此功能,如果是的话,我的客户端代码应该做什么来启用它?

1 个答案:

答案 0 :(得分:11)

为了能够根据RFC6531发送UTF-8字符,客户端和服务器都需要支持它。

如果您使用SmtpClient的.NET实现,那么您需要定位框架版本4.5,因为该实现支持SMTPUTF8扩展。

如果您设置了DeliveryFormat属性,那么您已完成客户端支持UTF8字符所需的操作:

using (var smtp = new SmtpClient())
{
    smtp.DeliveryFormat = SmtpDeliveryFormat.International;

    var message = new MailMessage(
        "my.email@gmail.com",
        "ëçïƒÖ@example.com",
        "UTF8",
        "Is UTF8 supported?");

    smtp.Send(message);
}

如果我们对Send方法进行反向工程,我们可以轻松地从您的问题中跟踪堆栈跟踪。您将找到此实现:

if (!allowUnicode && !MimeBasePart.IsAscii(this.userName, true))
{
    throw new SmtpException(SR.GetString("SmtpNonAsciiUserNotSupported", new object[]
    {
        this.Address
    }));
}

allowUnicode方法提供Send布尔值:

if (this.DeliveryMethod == SmtpDeliveryMethod.Network)
{
    return this.ServerSupportsEai && this.DeliveryFormat == SmtpDeliveryFormat.International;
}

现在这里是图片中的服务器。私有布尔ServerSupportsEai什么时候变为真?事实证明,在发送EHLO命令时SmptConnection调用了ParseExtensions

if (string.Compare(text, 0, "SMTPUTF8", 0, 8, StringComparison.OrdinalIgnoreCase) == 0)
{
    ((SmtpPooledStream)this.pooledStream).serverSupportsEai = true;
}

如果您想提前知道您的邮件服务器是否支持该扩展,您只需将一个telnet客户端(我使用putty)连接到您的smtp服务器并发送EHLO somename命令并检查结果。

在端口587上连接到smtp.gmail.com可以得到这个输出:

220 smtp.gmail.com ESMTP hx10sm19521922wjb.25 - gsmtp
EHLO fubar
250-smtp.gmail.com at your service, [2001:FFF:8bef:1:34d6:a247:FFFF:4620]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

注意最后一行:它包含我们所需的SMTPUTF8

TL;博士

为了能够在emailaddres中使用国际字符,请确保将DeliveryFormat设置为SmtpDeliveryFormat.International并使用支持SMTPUTF8扩展名的smtp服务器并在其EHLO命令中通告它。