Is msg.is_attachment() enough to get all the attachments from email in python, or should we check that msg.is_multipart() too?
I am searching for mails from a particular sender with a particular subject. I take the first email, and then want to retrieve the attachments from it.
I'm using imaplib.
My code -
_, mails = imap_client.search(None, f'(FROM "{sender}")', f'(SUBJECT "{subject}")')
first_mail = mails[0].split()[0]
mail_msgs = [email.message_from_bytes(response[1]) for response in first_mail if isinstance(response, tuple)]
msg = mail_msgs[0]
attachments = [part for part in msg.walk() if msg.is_multipart() and part.get_content_disposition() == "attachment"]
My question is regarding the last line -
to retrieve the attachments, do i need to check if the msg is both is_multipart()
and get_content_disposition()
attachments = [part for part in msg.walk() if msg.is_multipart() and part.get_content_disposition() == "attachment"]
or will only checking for get_content_disposition()
suffice?
attachments = [part for part in msg.walk() if part.get_content_disposition() == "attachment"]
Solution 1:
Possible bug
email.message_from_bytes()
is not guaranteed to return an email.message.EmailMessage
object. It returns an email.message.Message
object, which does not necessarily have the is_attachment()
method.
So you might want to pass _class=email.message.EmailMessage
to email.message_from_bytes()
.
Answer to the question
Message.is_multipart()
checks whether the message is a multipart message. This does not mean, that it contains an attachment file. It will also match emails, which are sent with dual text/html
and text/plain
bodies. If you want to filter multipart messages, this is all you need. If you want to filter file attachments, you want to filter using part.is_attachment()
on the messages parts. In the latter case, is_attachment()
is sufficient.