Python 3 smtplib 发送带有 Unicode 字符的邮件
我在用Python 3的smtplib发送包含Unicode字符的邮件时遇到了问题。在3.1.1版本中发送失败,但在2.5.4版本中可以正常工作:
import smtplib
from email.mime.text import MIMEText
sender = to = 'ABC@DEF.com'
server = 'smtp.DEF.com'
msg = MIMEText('€10')
msg['Subject'] = 'Hello'
msg['From'] = sender
msg['To'] = to
s = smtplib.SMTP(server)
s.sendmail(sender, [to], msg.as_string())
s.quit()
我尝试了文档中的一个例子,但也失败了。这个例子可以在这里找到:http://docs.python.org/3.1/library/email-examples.html,是关于将目录内容作为MIME消息发送的示例。
有没有什么建议?
2 个回答
MIMEText
的 _charset
参数默认是 us-ascii
,这在 文档 中有说明。因为 €
这个符号不在 us-ascii 的字符范围内,所以它无法正常工作。
你尝试的文档示例中明确提到:
在这个例子中,假设文本文件只包含 ASCII 字符。
你可以使用 .get_charset
方法来查看你的消息使用的字符集,顺便提一下,还有 .set_charset
方法。
关键在于文档里:
class email.mime.text.MIMEText(_text, _subtype='plain', _charset='us-ascii')
MIMEText类是MIMENonMultipart的一个子类,用来创建主要类型为文本的MIME对象。_text是要发送的文本内容。_subtype是次要类型,默认是普通文本。_charset是文本的字符集,作为参数传给MIMENonMultipart的构造函数,默认是us-ascii。文本数据不会进行任何猜测或编码处理。
所以你需要的显然不是msg = MIMEText('€10')
,而是:
msg = MIMEText('€10'.encode('utf-8'), _charset='utf-8')
虽然文档没有写得很清楚,但sendmail需要的是字节字符串,而不是Unicode字符串(这是SMTP协议的要求);你可以查看msg.as_string()
在两种构建方式下的表现——由于“没有猜测或编码”,你的方式里仍然包含那个欧元符号(sendmail无法将其转换为字节字符串),而我的方式没有这个符号(并且utf-8在整个过程中都有明确指定)。