繁体   English   中英

如何使用Python 3.2电子邮件模块发送带有quoted-printable的utf-8编码的unicode消息?

[英]How do I use Python 3.2 email module to send unicode messages encoded in utf-8 with quoted-printable?

我想在Python 3.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')将它从bytesstr是一个可怕的黑客攻击,我也不应该这样做。

email模块刚刚打破了编码? 我没有得到什么吗?

我试图只是简单地设置它,没有字符集。 这留给我一个unicode电子邮件消息,这根本不对。 我也尝试过了encodedecode步骤。 如果我将它们都关闭,它会在尝试确定是否需要在quoted-printable编码中引用该字符时抱怨超出范围。 如果我只留下encode步骤,它会痛苦地抱怨我是如何传递一个bytes而它想要一个str

该电子邮件包并不混淆哪个(编码的unicode与内容传输编码的二进制数据),但是文档没有说清楚,因为大部分文档都是从“编码” 意味着内容的时代开始的 -传输编码。 我们正在开发一个更好的API,这将使所有这些更容易grok(和更好的文档)。

实际上有一种方法可以让电子邮件包将QP用于utf-8机构,但它没有很好的记录。 你这样做:

>>> 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'

运行

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 '\א'是问题角色。 _QUOPRI_BODY_MAPquoprimime.py中定义

_QUOPRI_HEADER_MAP = dict((c, '=%02X' % c) for c in range(256))
_QUOPRI_BODY_MAP = _QUOPRI_HEADER_MAP.copy()

此dict仅包含range(256)中的键。 所以我认为你是对的; quoprimime.py不能用于编码任意unicode。

作为解决方法,您可以通过省略使用(默认)base64

c.body_encoding = email.charset.QP

请注意, 最新版本的quoprimime.py根本不使用_QUOPRI_BODY_MAP ,因此使用最新的Python可能会解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM