How to save an email attached in another using python smtplib?

1.4k views Asked by At

I am using python imaplib to download and save attachments in email. But when there is an email with attachment as another email, x.get_payload() is of Nonetype. I think these type of mails are are send using some email clients. Since the filename was missing, I tried changing filename in header followed by 'Content-Disposition'. The renamed file gets opened and when I try to write to that file using

fp.write(part.get_payload(decode=True))

it says string or buffer expected but Nonetype found.

>>>x.get_payload()
[<email.message.Message instance at 0x7f834eefa0e0>]
>>>type(part.get_payload())
<type 'list'>
>>>type(part.get_payload(decode=True))
<type 'NoneType'>

I removed decode=True and I got a list of objects

x.get_payload()[0]
<email.message.Message instance at 0x7f834eefa0e0>

I tried editing the filename in case email found as attachment.

if part.get('Content-Disposition'): 
    attachment = str(part.get_filename()) #get filename
    if attachment == 'None':
        attachment = 'somename.mail'
        attachment = self.autorename(attachment)#append (no: of occurences) to filename eg:filename(1) in case file exists
        x.add_header('Content-Disposition', 'attachment', filename=attachment)
        attachedmail = 1

 if attachedmail == 1:
     fp.write(str(x.get_payload()))
 else:
     fp.write(x.get_payload(decode=True)) #write contents to the opened file

and the file contains the object name file content is given below

[ < email.message.Message instance at 0x7fe5e09aa248 > ]

How can I write the contents of these attached emails to files?

1

There are 1 answers

0
cutteeth On BEST ANSWER

I solved it myself. as [ < email.message.Message instance at 0x7fe5e09aa248 > ] is a list of email.message.Message instances, each one have .as_string() method. In my case writing the content of .as_string() to a file helped me to extract the whole header data including embedded attachments to a file. Then I inspected the file line by line and saved contents based on the encoding and file type.

>>>x.get_payload()
[<email.message.Message instance at 0x7f834eefa0e0>]
>>>fp=open('header','wb')
>>>fp.write(x.get_payload()[0].as_string())
>>>fp.close()
>>>file_as_list = []
>>>fp=open('header','rb')
>>>file_as_list = fp.readlines()
>>>fp.close()

And then inspecting each lines in file

for x in file_as_list:
    if 'Content-Transfer-Encoding: quoted-printable' in x:
        print 'qp encoded data found!'
    if 'Content-Transfer-Encoding: base64' in x:
        print 'base64 encoded data found!'  

The encoded data representing inline(embedded) attachments can be skipped as imaplib already captures it.