栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在Python中将电子邮件发送到具有非ASCII字符的地址?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在Python中将电子邮件发送到具有非ASCII字符的地址?

电子邮件地址是否打算成为全世界唯一的ASCII码?

没有; 其实恰恰相反。电子邮件地址 ASCII只。它们 旨在 成为Unipre,而我们正在那里。这只是一个缓慢的过渡。


在现代电子邮件中,电子邮件地址分为两部分:1
DNS主机名(位于后面的部分

@
)和该主机上的邮箱(位于之前的部分
@
)。它们受完全不同的标准支配,因为DNS必须为HTTP和除电子邮件之外的所有其他方式工作。


DNS的上一次更新是在1987年的RFC
1035中
,它规定了ASCII的受限子集(以及不区分大小写)。

但是,RFC
5890中指定的IDNA(应用程序国际化域名)允许应用程序有选择地将Unipre字符集的很大一部分映射到DNS名称,以呈现给用户。

因此,您不能拥有域名

dómain.com
。但是您 可以 拥有域名
xn--dmain-0ta.com
。并且许多应用程序会接受
dómain.com
用户输入并自动进行翻译,然后接受
xn--dmain-0ta.com
网络并将其显示为
dómain.com
。2

在Python中,一些用于互联网协议的库会自动为您IDNA编码域名;否则不会。如果没有,则可以手动进行操作,如下所示:

>>> 'dómain.com'.enpre('idna')b'xn--dmain-0ta.com'

请注意,在3.x中,这是a

bytes
,而不是a
str
;如果您需要
str
,则可以随时执行以下操作:

>>> 'dómain.com'.enpre('idna').depre('ascii')'xn--dmain-0ta.com'

邮箱名称由SMTP定义,最近一次在RFC 5321和RFC
5322中定义,这清楚地表明,如何解释地址的“本地部分”完全取决于接收主机。例如,大多数电子邮件服务器使用不区分大小写的名称。许多允许“加标签”(例如,

shule@gmail.com
并且
shule+so@gmail.com
是同一邮箱);一些(例如gmail)忽略所有点;等等

问题是SMTP从未指定标头使用什么字符集。传统的SMTP服务器仅是7位ASCII,因此直到最近,实际上,您只能在标题中使用ASCII,因此在邮箱名称中也只能使用ASCII。

RFC
6530和相关提案中指定的EAI(电子邮件地址国际化)允许在SMTP会话中协商UTF-8。在UTF-8会话中,标头以及这些标头中的地址被解释为UTF-8。(主机名的IDNA编码不是必需的,但仍然允许。)

太好了,但是如果您的客户端,服务器,收件人的服务器或任何中继服务器在此过程中不讲SMTPUTF8,该怎么办?为了处理这种情况,每个拥有UTF-8邮箱的人也都对该邮箱使用ASCII名称。理想情况下,该消息将与消息一起发送,并且当链中的最后一个SMTPUTF8程序遇到第一个非SMTPUTF8程序时,将切换为ASCII替换。更常见的是,它只是收到一条错误消息,然后将其传播回用户以进行手动处理。3

这个想法是,最终,Internet上的大多数主机都将使用SMTPUTF8,因此您可以使用SMTPUTF8,

úßerñame@dómain.com
但是与此同时,您的服务器上
dómain.com
úßerñame
并且
ussernyame
作为同一邮箱的别名。任何无法处理SMTPUTF8的人都将看到您(并且必须引用您)为
ussernyame
。(实际上,他们的邮件客户端会将您视为
ussernyame@xn--dmain-0ta.com
,但它可以修复最后一部分;如果在运输过程中丢失了第一部分,它将无能为力。)

截至2018年中,大多数主机不讲SMTPUTF8,许多客户端库也不讲。

从Python
3.5(4)开始,标准库

smtplib
支持
SMTPUTF8
。如果您正在使用高级
sendmail
功能:

如果

SMTPUTF8
mail_options中包含且服务器支持,则 from_addrto_addrs 可能包含非ASCII字符。

因此,您要做的是这样的:

try:    server.sendmail([fromaddr], [toaddr], msg, mail_options=['SMTPUTF8'])except SMTPNotSupportedError:    server.sendmail([fromaddr_ascii], [toaddr_ascii], msg)

(从理论上讲,最好使用来检查EHLO响应

has_extn
,但在实践中,只需尝试似乎更平稳即可。随着服务器生态系统和/或将来的改进,这种情况可能会改变
smptlib
。)

你从哪里得到的是

fromaddr_ascii
toaddr_ascii
?这取决于您的程序。在DNS部分,您只使用IDNA,但是对于邮箱部分,则没有这样的规则。您必须知道邮箱的备用ASCII邮箱名称。也许你问用户。也许您有一个数据库,其中存储了具有EAI和传统地址的联系人。也许您只担心一个特定的域,并且知道它使用了可以实施的某些规则。


1.实际上,addr-spec由两部分组成;一个 地址 是一个地址规格的加上可选的显示名称和注释。但是没关系。

2.有一些例外。例如,如果键入

http://staсkoverflow.com
,则浏览器可能警告您,西里尔小写Es代替拉丁小写Cee可能是劫持尝试。或者,如果您尝试导航到
http://dómain.com
,则错误页面可能会告诉您该域不存在的错误页面
xn--dmain-0ta.com
,因为这对于调试更有用。

3.这是希望随着时间的推移会变得更好的事情之一,但是可能直到变得无所谓后,它才能变得不够好……

4.如果您使用的是Python
3.4或2.7,该怎么办?那么您就没有SMTPUTF8支持。升级,而不是寻找第三方库

smtplib
,或者编写您自己的SMTP代码。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/646641.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号