无法向带有斯堪的纳维亚字符的地址发送电子邮件 [英] Cannot send emails to addresses with Scandinavian characters
问题描述
使用 SmtpClient
、MailMessage
和 MailAddress
类,我无法发送到电子邮件地址,例如 åbc.def@domain.se.我收到如下所示的错误/异常:
在邮件标题中发现无效字符:'å'.
<块引用>
--------------------------- 发送电子邮件时出错--------------------------- System.Net.Mail.SmtpException: 客户端或服务器仅配置为使用 ASCII 的电子邮件地址本地部分:åbc.def@domain.se.
在 System.Net.Mail.MailAddress.GetUser(Boolean allowUnicode)
在 System.Net.Mail.MailAddress.GetAddress(Boolean allowUnicode)
在 System.Net.Mail.MailAddress.Encode(Int32 charsConsumed, Boolean允许Unicode)
在 System.Net.Mail.MailAddressCollection.Encode(Int32charsConsumed, Boolean allowUnicode)在 System.Net.Mail.Message.PrepareHeaders(Boolean sendEnvelope,布尔值allowUnicode)在 System.Net.Mail.Message.Send(BaseWriter writer, BooleansendEnvelope,布尔值allowUnicode)在 System.Net.Mail.SmtpClient.Send(MailMessage message)
我的主题/正文中的这些字符没问题,但电子邮件地址中的这些字符不行.
我试过设置 SmtpClient.DeliveryMethod = SmtpDeliveryFormat.International
或 MailMessage.HeadersEncoding = Encoding.Unicode
(或 UTF8
)和它似乎没有改变任何东西.这些是我们需要与之交流的人的真实电子邮件地址,所以这有点问题.
我一直在挖掘 .Net 源代码,但没有真正得到任何地方.我找到了一个 ServerSupportsEai
属性,Google 告诉我 EAI 代表电子邮件地址国际化 (https://www.rfc-editor.org/rfc/rfc5336)但目前还不清楚这是否是我的代码中的限制,或者我正在与之交谈的特定服务器没有支持这个...因为我使用测试服务器来避免向毫无戒心的瑞典人发送电子邮件!
有人可以帮我解决这个问题 - .Net 是否支持这一点,如果支持的话,如果我的客户端代码应该做些什么来启用它呢?
能够根据RFC6531 客户端和服务器都需要支持.
如果您使用 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",支持UTF8吗?");smtp.Send(message);}
如果我们对 Send
方法进行逆向工程,我们可以轻松跟踪您问题中的堆栈跟踪.你会发现这个实现:
if (!allowUnicode && !MimeBasePart.IsAscii(this.userName, true)){throw new SmtpException(SR.GetString(SmtpNonAsciiUserNotSupported", new object[]{这个地址}));}
allowUnicode
布尔值由 Send
方法提供:
if (this.DeliveryMethod == SmtpDeliveryMethod.Network){返回 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 - gsmtpEHLO 富巴250-smtp.gmail.com 为您服务,[2001:FFF:8bef:1:34d6:a247:FFFF:4620]250 码 35882577250-8BITMIME250-STARTTLS250 增强状态代码250-流水线250 块250 SMTPUTF8
注意最后一行:它保存了我们需要的 SMTPUTF8
tl;博士
为了能够在电子邮件地址中使用国际字符,请确保将 DeliveryFormat
设置为 SmtpDeliveryFormat.International
并使用支持 SMTPUTF8 扩展的 smtp 服务器并对其进行广告在其 EHLO
命令中.
Using SmtpClient
, MailMessage
and MailAddress
classes, I cannot send to email addresses such as åbc.def@domain.se. I get the error/exceptions as shown below:
An invalid character was found in the mail header: 'å'.
--------------------------- Error sending email --------------------------- System.Net.Mail.SmtpException: The client or server is only configured for E-mail addresses with ASCII local-parts: å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)
These characters in my subject/body are fine, but not in email addresses.
I've tried setting SmtpClient.DeliveryMethod = SmtpDeliveryFormat.International
, or MailMessage.HeadersEncoding = Encoding.Unicode
(or UTF8
) and it doesn't seem to change anything. These are real email addresses of people we need to communicate with so it's a bit of a problem.
I have been digging through the .Net source code but not really gotten anywhere. I tracked down a ServerSupportsEai
property, and Google tells me EAI stands for Email Address Internationalisation (https://www.rfc-editor.org/rfc/rfc5336) but it's fairly unclear if this is a limitation in my code, or if the specific server I'm talking to just doesn't support this... since I'm using a test server to avoid sending emails to unsuspecting Swedish people!
Can someone help me clear this up - does .Net support this, if so what if anything should my client code do to enable it?
To be able to to send UTF-8 characters according to RFC6531 both client and server need to support it.
If you use the .NET implementation of SmtpClient
you'll need to target framework version 4.5 because that implementation supports the SMTPUTF8 extension.
If you set the DeliveryFormat
property you have done what is needed for your client to support UTF8 characters:
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);
}
If we reverse-engineer the Send
method we can easily follow the stack-trace from your question. You'll find this implementation:
if (!allowUnicode && !MimeBasePart.IsAscii(this.userName, true))
{
throw new SmtpException(SR.GetString("SmtpNonAsciiUserNotSupported", new object[]
{
this.Address
}));
}
That allowUnicode
boolean is being supplied from the Send
method:
if (this.DeliveryMethod == SmtpDeliveryMethod.Network)
{
return this.ServerSupportsEai && this.DeliveryFormat == SmtpDeliveryFormat.International;
}
Now here comes the server in the picture. When does the private boolean ServerSupportsEai
becomes true? It turns out that on sending the EHLO
command the SmptConnection
calls ParseExtensions
:
if (string.Compare(text, 0, "SMTPUTF8", 0, 8, StringComparison.OrdinalIgnoreCase) == 0)
{
((SmtpPooledStream)this.pooledStream).serverSupportsEai = true;
}
If you want to know upfront if your mail server is supporting that extension you can simply connect with a telnet client (I use putty) to your smtp server and send the EHLO somename
command and inspect the results.
Connecting to smtp.gmail.com
on port 587 gives me this output:
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
Notice the last line: it holds our required SMTPUTF8
tl;dr
To be able to use international characters in the emailaddres make sure to set the DeliveryFormat
to SmtpDeliveryFormat.International
and use an smtp server that supports the SMTPUTF8 extension and advertises it in its EHLO
command.
这篇关于无法向带有斯堪的纳维亚字符的地址发送电子邮件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!