pythonemailimapimapclient

Interaction between Python IMAPClient library and email package


I have a Django project where I am working on an email client. I've decided to use python's IMAPClient instead of standard library's imaplib for getting access to the messages. Currently, I don't make use of python's email package to encode/decode responses received from IMAPClient, and I have a feeling that I manually implement things that should be handled by email.

Example code for downloading attachment:

def download_attachment(server, msgid, index, encoding):
    # index and encoding is known from previous analysis of bodystructure
    file_content = f_fetch(server, msgid, index)
    # the below code should be handled by email's message_from_bytes 
    # and subsequent get_payload(decode = True) function
    if encoding == 'base64':
        file_content = base64.b64decode(file_content)
    elif ...
    ...
    endif
    #writing file_content to a folder
    return

def f_fetch(server, msgid, index):
    if not index:
        index = '1'
    response = server.fetch(msgid, 'BODY[' + index + ']')
    key = ('BODY[' + index + ']').encode('utf-8')
    if type(msgid) is str:
        msgid = int(msgid)
    return response[msgid][key]

So the question is, how should I rewrite this code to make use of email. Specifically, what should I do with the response from IMAPClient to pass it to email's message_from_bytes() function?


Solution

  • If you wish to parse an email using the email package's message_from_bytes() function then you need to give it the entire, raw email body. To get this, fetch using the RFC822 selector like this:

    fetch_data = server.fetch(msgid, ['RFC822'])
    parsed = email.message_from_bytes(fetch_data[msgid][b'RFC822'])
    

    If you're pulling individual message parts/attachments from the IMAP server, then the server is effectively doing the parsing work for you and you don't need to use the email package's parser.