28

I am displaying new email with IMAP, and everything looks fine, except for one message subject shows as:

=?utf-8?Q?Subject?=

How can I fix it?

3
  • "How can I fix it?" - Why do you assume that it is broken? Commented Oct 15, 2012 at 21:01
  • 1
    It should show just "Subject" - what's inside the =?utf-8?Q? ... ? Commented Oct 15, 2012 at 21:02
  • 1
    en.wikipedia.org/wiki/… Commented Oct 15, 2012 at 21:03

6 Answers 6

34

In MIME terminology, those encoded chunks are called encoded-words. You can decode them like this:

import email.header
text, encoding = email.header.decode_header('=?utf-8?Q?Subject?=')[0]

Check out the docs for email.header for more details.

Sign up to request clarification or add additional context in comments.

1 Comment

In both Python 2 and Python 3, email.header.decode_header (with lower-case m) is the generic name. In addition, in your code, text is not actually a text, but instead a bytes variable.
18

The text is encoded as a MIME encoded-word. This is a mechanism defined in RFC2047 for encoding headers that contain non-ASCII text such that the encoded output contains only ASCII characters.

In Python 3.3+, the parsing classes and functions in email.parser automatically decode "encoded words" in headers if their policy argument is set to policy.default

>>> import email
>>> from email import policy

>>> msg = email.message_from_file(open('message.txt'), policy=policy.default)
>>> msg['from']
'Pepé Le Pew <[email protected]>'

The parsing classes and functions are:

Confusingly, up to at least Python 3.10, the default policy for these parsing functions is not policy.default, but policy.compat32, which does not decode "encoded words".

>>> msg = email.message_from_file(open('message.txt'))
>>> msg['from']
'=?utf-8?q?Pep=C3=A9?= Le Pew <[email protected]>'

Comments

16

This is a MIME encoded-word. You can parse it with email.header:

import email.header

def decode_mime_words(s):
    return u''.join(
        word.decode(encoding or 'utf8') if isinstance(word, bytes) else word
        for word, encoding in email.header.decode_header(s))

print(decode_mime_words(u'=?utf-8?Q?Subject=c3=a4?=X=?utf-8?Q?=c3=bc?='))

2 Comments

Could you rewrite that in a more Pythonic fashion?
@wbg What's not Pythonic about this code? What would you change? Looking at it now, it seems rather well-written to me, and a paragon of Python's expressiveness. Maybe the generator expression is tripping up @deterjan? If you're just targeting Python 3, you can skip the if isinstance(word, bytes) else word and the u before the '; this code has been engineered to work on both Python 2 and 3.
6

Try Imbox

Because imaplib is a very excessive low level library and returns results which are hard to work with

Installation

pip install imbox

Usage

from imbox import Imbox

with Imbox('imap.gmail.com',
        username='username',
        password='password',
        ssl=True,
        ssl_context=None,
        starttls=False) as imbox:

    all_inbox_messages = imbox.messages()
    for uid, message in all_inbox_messages:
        message.subject

1 Comment

+1 truly this is for humans. Indeed imbox was able to decode otherwise base64-encoded (in imaplib and the like) subject and other fields on-the-fly. However, be aware if some field is missing the KeyError will be thrown.
5

In Python 3, decoding this to an approximated string is as easy as:

from email.header import decode_header, make_header

decoded = str(make_header(decode_header("=?utf-8?Q?Subject?=")))

See the documentation of decode_header and make_header.

Comments

1

High level IMAP lib may be useful here: imap_tools

from imap_tools import MailBox, AND

# get list of email subjects from INBOX folder
with MailBox('imap.mail.com').login('[email protected]', 'pwd', 'INBOX') as mailbox:
    subjects = [msg.subject for msg in mailbox.fetch()]
  • Parsed email message attributes
  • Query builder for searching emails
  • Actions with emails: copy, delete, flag, move, seen
  • Actions with folders: list, set, get, create, exists, rename, delete, status
  • No dependencies

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.