Petr Baudis Petr Baudis - 1 year ago 53
Python Question

How to send emails with names in headers from Python

I need to send nice-looking emails from Python with address headers that contain names - somehow something that never pops up in tutorials.

I'm using email.mime.text.MIMEText() to create the email, but setting

msg['To'] = 'á <>'
rather than utf8-encoding only the name part, will utf8-encode the whole header value, which of course fails miserably. How to do this correctly?

I have found a sort-of solution Python email module: form header "From" with some unicode name + email but it feels hard to accept such a hack, since there does seem to be some support for handling this automatically in Python's email package in email.headerregistry which should be used automatically as far as I can see, but it doesn't happen.

Answer Source

You have to use the right policy from email.policy to get the correct behaviour.

Wrong Policy

email.message.Message will use email.policy.Compat32 by default. That one was designed for backward-compatibility wih older Python versions and does the wrong thing:

>>> msg = email.message.Message(policy=email.policy.Compat32())
>>> msg['To'] = 'ššššš <>'
>>> msg.as_bytes()
b'To: =?utf-8?b?xaHFocWhxaHFoSA8c3Nzc0BleGFtcGxlLmNvbT4=?=\n\n'

Correct Policy

email.policy.EmailPolicy will do what you want:

>>> msg = email.message.Message(policy=email.policy.EmailPolicy())
>>> msg['To'] = 'ššššš <>'
>>> msg.as_bytes()
b'To: =?utf-8?b?xaHFocWhxaHFoQ==?= <>\n\n'

Python 2.7

With older Python versions (eg 2.7), you have to use the "hack" as you called it:

>>> msg = email.message.Message()
>>> msg['To'] = email.header.Header(u'ššššš').encode() + ' <>'
>>> msg.as_string()
'To: =?utf-8?b?xaHFocWhxaHFoQ==?= <>\n\n'