Search code examples
pythonimaplib

How can I get an attached eml file from email message content using Python?


I am using python 3.7 and the email, imap library to read email and extract the content of email and attachments, all the attachment (like excel, csv, pdf) is downloading as attachment but when I received any .eml file in email, it shows me an error. Please find the below code to read email content and attachment with error showing in case of eml file is received as attachment.

It is showing error at the time of writing eml file. at the time of write part.get_payload(decode=True) is coming blank in eml file case.

filename = part.get_filename()
if filename is not None:
    dot_position = filename.find('.')
    file_prefix = filename[0:dot_position]
    file_suffix = filename[dot_position:len(filename)]
    now = datetime.datetime.now()
    timestamp = str(now.strftime("%Y%m%d%H%M%S%f"))
    newFileName = file_prefix + "_" + timestamp + file_suffix
    sv_path = os.path.join(svdir, newFileName)
    mydict = filename + '$$' + newFileName
    mydict1 = mydict1 + ',' + mydict
    print(mydict1)
    if not os.path.isfile(sv_path):
        print("oldpath:---->" + sv_path)
        fp = open(sv_path, 'wb')
        print(part.get_payload(decode=True))
        fp.write(part.get_payload(decode=True))
        fp.close()

Error is

<class 'TypeError'> ReadEmailUsingIMAP.py 129
a bytes-like object is required, not 'NoneType'

Solution

  • Just to explain why this is happening (it hit me too), quoting the v. 3.5 library doc. (v2 says the same):

    If the message is a multipart and the decode flag is True, then None is returned.

    If your attachment is an .EML, it's almost always going to be multi-part, thus the None.

    Jin Thakur's workaround is appropriate if you're only expecting .EML multipart attachments (not sure if there is any other use cases); it should have been accepted as an answer.