1

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'] = 'á <x@y.cz>' 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.

Community
  • 1
  • 1
Petr Baudis
  • 1,178
  • 8
  • 13

1 Answers1

3

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'] = 'ššššš <ssss@example.com>'
>>> 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'] = 'ššššš <ssss@example.com>'
>>> msg.as_bytes()
b'To: =?utf-8?b?xaHFocWhxaHFoQ==?= <ssss@example.com>\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() + ' <ssss@example.com>'
>>> msg.as_string()
'To: =?utf-8?b?xaHFocWhxaHFoQ==?= <ssss@example.com>\n\n'
zvone
  • 18,045
  • 3
  • 49
  • 77