Get an int type from python fetch() function (email module)

Question:

When I was using the email module to download attachments, I had a very strange problem. Here is my code

import imaplib
import email
import os
import time

download_folder = "/Users/zonghan/Desktop"


def get_mail(username, passsword):
    server = imaplib.IMAP4_SSL('imap.gmail.com')
    server.login(username, passsword)
    server.select("INBOX")
    email_type, items = server.search(None, "UNSEEN")
    msg_list = items[0].split()
    for email_id in msg_list:
        print(f'id:{email_id}')
        email_type, data = server.fetch(email_id, "(RFC822)")
        print(data[0])
        email_body = data[0][1]
        print(email_body, type(email_body))

        mail = email.message_from_bytes(email_body)
        temp = server.store(email_id, '+FLAGS', '\Seen')
        server.expunge()
        for part in mail.walk():
            if part.get_content_maintype() == 'multipart':
                pass


The message_from_bytes method will report an error when reading more than two unread messages.

id:b'62'
(b'62 (RFC822 {39416}', body info...)
body info...  <class 'bytes'>
id:b'63'
b'62 (UID 62 FLAGS (\Seen))'
50 <class 'int'>

Traceback (most recent call last):
  File "/Users/zonghan/PycharmProjects/djangotest/app01/about_email.py", line 71, in <module>
    get_mail(username, password)
  File "/Users/zonghan/PycharmProjects/djangotest/app01/about_email.py", line 36, in get_mail
    mail = email.message_from_bytes(email_body)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/email/__init__.py", line 46, in message_from_bytes
    return BytesParser(*args, **kws).parsebytes(s)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/email/parser.py", line 123, in parsebytes
    text = text.decode('ASCII', errors='surrogateescape')
AttributeError: 'int' object has no attribute 'decode'

Here is my email

e-mail

I don’t know why I return an int instead of a byte, and why I get an error every time I read the email a second time.

Asked By: hans

||

Answers:

I saw the problem and fixed it, but I don’t know if it works for everyone
The reason for this problem is that when the second email is read, an extra message will be returned, and the message that was read last will be returned. Therefore, data[0][1] should be replaced by data[1][1], and the correct data will be obtained

import imaplib
import email
import os
import time

download_folder = "/Users/zonghan/Desktop"


def get_mail(username, passsword):
    server = imaplib.IMAP4_SSL('imap.gmail.com')
    server.login(username, passsword)
    server.select("INBOX")
    email_type, items = server.search(None, "UNSEEN")
    msg_list = items[0].split()
    count = 0
    for email_id in msg_list:
        print(f'id:{email_id}')
        email_type, data = server.fetch(email_id, "(RFC822)")
        if count == 0:
            email_body = data[0][1]
            count = 1
        else:
            email_body = data[1][1]
        
        mail = email.message_from_bytes(email_body)
        temp = server.store(email_id, '+FLAGS', '\Seen')
        server.expunge()
        for part in mail.walk():
            if part.get_content_maintype() == 'multipart':
                pass
Answered By: hans
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.