Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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)]
    # print(dot_position)
    # print(file_prefix)
    # print(file_suffix)
    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)
    # allfiles = allfiles.append([{"oldfilename": filename, "newfilename": newFileName}])
    mydict = filename + '$$' + newFileName
    mydict1 = mydict1 + ',' + mydict
    print(mydict1)
    if not os.path.isfile(sv_path):
        print("oldpath:---->" + sv_path)
        # filename = os.rename(filename, filename + '_Rahul')
        # sv_path = os.path.join(svdir, filename)
        # print("Newpath:---->" + sv_path)
        fp = open(sv_path, 'wb')
        # print("Rahul")
        print(part.get_payload(decode=True))
        # try:
        # newFileByteArray = bytearray(fp)
        # if part.get_payload(decode=True) is not None:
        fp.write(part.get_payload(decode=True))
        # except (TypeError, IOError):
        #    pass
        fp.close()

Error is

<class 'TypeError'> ReadEmailUsingIMAP.py 129
a bytes-like object is required, not 'NoneType'
like image 742
Rahul Gour Avatar asked Nov 15 '22 21:11

Rahul Gour


2 Answers

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.

like image 160
Erik Knowles Avatar answered Dec 04 '22 05:12

Erik Knowles


Use eml_parser https://pypi.org/project/eml-parser/ import datetime import json import eml_parser

def json_serial(obj):
    if isinstance(obj, datetime.datetime):
        serial = obj.isoformat()
        return serial


with open('sample.eml', 'rb') as fhdl:
    raw_email = fhdl.read()

parsed_eml = eml_parser.eml_parser.decode_email_b(raw_email)

print(json.dumps(parsed_eml, default=json_serial))
like image 20
Jin Thakur Avatar answered Dec 04 '22 06:12

Jin Thakur