我想在Python3.2程序中发送具有任意unicode正文的电子邮件。但是,实际上,这些消息将主要由7位ASCII文本组成。因此,我希望使用quoted-printable对utf-8中的消息进行编码。到目前为止,我发现这是可行的,但它似乎是错误的:
c = email.charset.Charset('utf-8')
c.body_encoding = email.charset.QP
m = email.message.Message()
m.set_payload("My message with an '\u05d0' in it.".encode('utf-8').decode('iso8859-1'), c)这会产生一封内容恰到好处的电子邮件:
To: someone@example.com
From: someone_else@example.com
Subject: This is a subjective subject.
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
My message with an '=D7=90' in it.特别是,b'\xd7\x90'.decode('utf-8')会产生原始的Unicode字符。因此,quoted-printable编码可以正确地呈现utf-8。我很清楚这是一个非常丑陋的黑客攻击。但它是有效的。
这是Python 3。文本字符串应该始终是unicode。我不应该把它解码成utf-8的。然后通过.decode('iso8859-1')将它从bytes转换回str是一个可怕的技巧,我也不应该这样做。
是不是email模块在编码方面出了问题?我是不是没得到什么?
我尝试了简单的旧式设置,没有字符集。这给我留下了一条unicode电子邮件消息,这是完全不正确的。我还试着去掉encode和decode的步骤。如果我将它们都去掉,它会在尝试确定该字符是否需要在带引号的可打印编码中加引号时报告\u05d0超出范围。如果我只在encode步骤中离开,它就会抱怨我传入了一个bytes,它想要一个str。
发布于 2012-03-01 10:18:21
该电子邮件包不会混淆哪一个是哪一个(编码的unicode和内容传输编码的二进制数据),但文档并不是很清楚,因为大部分文档都可以追溯到“编码”意味着内容传输编码的时代。我们正在开发一个更好的API,它将使这一切更容易理解(以及更好的文档)。
实际上,有一种方法可以让电子邮件包对utf-8正文使用QP,但没有很好的文档记录。你可以这样做:
>>> charset.add_charset('utf-8', charset.QP, charset.QP)
>>> m = MIMEText("This is utf-8 text: á", _charset='utf-8')
>>> str(m)
'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\nThis is utf-8 text: =E1'发布于 2012-02-23 06:00:50
正在运行
import email
import email.charset
import email.message
c = email.charset.Charset('utf-8')
c.body_encoding = email.charset.QP
m = email.message.Message()
m.set_payload("My message with an '\u05d0' in it.", c)
print(m.as_string())生成此回溯消息:
File "/usr/lib/python3.2/email/quoprimime.py", line 81, in body_check
return chr(octet) != _QUOPRI_BODY_MAP[octet]
KeyError: 1488因为
In [11]: int('5d0',16)
Out[11]: 1488很明显,unicode '\u05d0'是问题字符。在quoprimime.py中,通过以下方式定义_QUOPRI_BODY_MAP
_QUOPRI_HEADER_MAP = dict((c, '=%02X' % c) for c in range(256))
_QUOPRI_BODY_MAP = _QUOPRI_HEADER_MAP.copy()此字典仅包含来自range(256)的密钥。所以我认为你是对的;quoprimime.py不能用来编码任意的unicode。
作为一种变通办法,您可以通过省略使用(缺省的) base64
c.body_encoding = email.charset.QP注意,quoprimime.py的latest version根本不使用_QUOPRI_BODY_MAP,所以使用最新的Python可能会解决这个问题。
https://stackoverflow.com/questions/9403265
复制相似问题