无法向带有斯堪的纳维亚字符的地址发送电子邮件。

11
使用SmtpClientMailMessageMailAddress类,我无法发送至如åbc.def@domain.se这样的电子邮件地址。我收到以下显示错误/异常:

在邮件头中找到一个无效字符:'å'。

---------------------------发送电子邮件时出错----------------------------

System.Net.Mail.SmtpException: 客户端或服务器只配置了 ASCII 本地部分的电子邮件地址:åbc.def@domain.se。

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

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

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

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

我的主题/正文中的这些字符是可以的,但不适用于电子邮件地址。

我尝试设置SmtpClient.DeliveryMethod = SmtpDeliveryFormat.International,或者MailMessage.HeadersEncoding = Encoding.Unicode(或UTF8),但似乎没有改变任何东西。这些是我们需要与之沟通的真实人员电子邮件地址,所以这是一个有点麻烦的问题。

我一直在查看.Net源代码,但真正没有收获。我找到了一个ServerSupportsEai属性,谷歌告诉我EAI代表电子邮件地址国际化(https://www.rfc-editor.org/rfc/rfc5336),但这是否是我的代码的限制还是我正在通信的特定服务器不支持它,因为我正在使用测试服务器避免向不知情的瑞典人发送电子邮件,所以这还不太清楚!

有人能帮我澄清一下吗 - .Net支持这个吗?如果支持,我的客户端代码需要做什么来启用它?


我认为问题可能不在.NET代码中,而是在您的电子邮件服务器配置中。您可以尝试使用另一个服务器吗? - Pikoh
1
此功能需要SMTP服务器支持SMTPUTF8,建议使用Gmail进行尝试,因为它支持该协议。如果成功了,则说明您的服务器存在问题。建议更换SMTP服务器或联系管理员解决。注意:5336已被替换为6531/2。 - Alex K.
谢谢。在与 Gmail 的“您的应用程序未使用最新安全性并已被阻止”作斗争后,我正在测试这个 - 尽管我仍然无法向真实的人发送邮件,但非常礼貌。 - Mr. Boy
有没有办法查看哪些广泛使用的电子邮件服务器支持这个功能? - Mr. Boy
1
也许你可以在这里(https://en.wikipedia.org/wiki/Extended_SMTP)获取一些信息。 - Pikoh
1个回答

16

要能够根据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 变为 true?结果发现,在发送 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。

太长不看:

为了能在电子邮件地址中使用国际字符,请确保将 DeliveryFormat设置为 SmtpDeliveryFormat.International 并使用支持SMTPUTF8扩展并在其EHLO命令中进行广告宣传的SMTP服务器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接