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

家住魔仙堡 提交于 2019-11-30 13:51:47

That email package isn't confused about which is which (encoded unicode versus content-transfer-encoded binary data), but the documentation does not make it very clear, since much of the documentation dates from an era when "encoding" meant content-transfer-encoding. We're working on a better API that will make all this easier to grok (and better docs).

There actually is a way to get the email package to use QP for utf-8 bodies, but it isn't very well documented. You do it like this:

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

Running

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())

Yields this traceback message:

  File "/usr/lib/python3.2/email/quoprimime.py", line 81, in body_check
    return chr(octet) != _QUOPRI_BODY_MAP[octet]
KeyError: 1488

Since

In [11]: int('5d0',16)
Out[11]: 1488

it is clear that the unicode '\u05d0' is the problem character. _QUOPRI_BODY_MAP is defined in quoprimime.py by

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

This dict only contains keys from range(256). So I think you are right; quoprimime.py can not be used to encode arbitrary unicode.

As a workaround, you could use (the default) base64 by omitting

c.body_encoding = email.charset.QP

Note that the latest version of quoprimime.py does not use _QUOPRI_BODY_MAP at all, so using the latest Python might fix the problem.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!