【问题标题】:Python 3 smtplib send with unicode charactersPython 3 smtplib 使用 unicode 字符发送
【发布时间】:2009-09-15 19:22:08
【问题描述】:

我在 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.5.4 中,它发送时没有错误消息,但将 '€' 替换为 '?'。

标签: python email unicode python-3.x smtplib


【解决方案1】:

密钥在the docs:

class email.mime.text.MIMEText(_text, _subtype='plain', _charset='us-ascii')

MIMENonMultipart 的子类, MIMEText 类用于创建 MIME 主要类型文本的对象。 _text 是 有效载荷的字符串。 _子类型 是次要类型,默认为 清楚的。 _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)。

【讨论】:

  • 发送而不生成错误消息。我发送到 Thunderbird 和 gmail。 Thunderbird 仅显示 10 作为消息文本。 Gmail 显示了完整的 10 欧元。 Python 以 'content-transfer-encoding: base64' 发送,而 Thunderbird 以 'content-transfer-encoding: 8-bit' 发送 10 欧元,而 gmail 以 'multipart/alternative; bounding=...' 对于生成 Thunderbird 可以解释的消息有什么建议吗?
  • 我不是 Thunderbird 专家,但请尝试其他编码,例如 iso-8859-15。尽管现在任何不能正确执行 utf-8 的程序都值得扔进历史的垃圾箱,请注意!-)
  • 问题好像不是iso-8859-15或者utf-8,好像是content-transfer-encoding。我检查的其他所有内容都使用 8 位,而 python 使用 base64。将标头强制为 8 位无济于事。使用 quopri.encodestring() 可能会获得 8 位编码,但我无法弄清楚如何使其工作。
【解决方案2】:

MIMEText_charset 参数根据docs 默认为us-ascii。由于 不是来自 us-ascii 集,因此无法正常工作。

您尝试过的文档中的示例明确指出:

对于本示例,假设文本文件仅包含 ASCII 字符。

您可以在消息中使用.get_charset 方法来调查字符集,顺便提一下.set_charset

【讨论】:

  • 如你所说,字符集是us-ascii,不包括€。在 msg 上使用 set_charset 并不能解决问题。问题(我应该更准确)在 sendmail 行 - UnicodeEncodeError: 'ascii' codec can't encode character '\x80' in position 161: ordinal not in range(128) 我读到这意味着我有对文本进行编码,使所有内容都在范围内(128),但我无法弄清楚如何。
  • 我正在查看示例页面上的第三个示例,发送整个目录。我尝试使用示例发送一个包含单个 zip 文件的目录。这失败了。
猜你喜欢
  • 2012-01-09
  • 2019-01-20
  • 2017-11-19
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
  • 2021-08-10
  • 2016-04-29
  • 1970-01-01
相关资源
最近更新 更多