Marshall Gu
Marshall Gu

Reputation: 137

Downloading excel attachments using imaplib

There's an email blasted out every morning containing an Excel attachment. I would like to be able to grab each of these attachments and save them into the same folder. I attempted the following code:

Downloading multiple attachments using imaplib

https://gist.github.com/jasonrdsouza/1674794

https://gist.github.com/baali/2633554

But I keep running into the same error:

initial_value must be str or None, not bytes

I assume this is because there's something wrong with one of the emails/attachments, but I'm not sure how to troubleshoot.

Code:

detach_dir = 'C:/Users/myname'
m = imaplib.IMAP4_SSL("outlook.office365.com")
m.login('[email protected]','password')
m.select("INBOX")

resp, items = m.search(None, '(SUBJECT "Daily Report")')
items = items[0].split()

for emailid in items:
    resp, data = m.fetch(emailid, "(RFC822)") 
    email_body = data[0][1] 
    mail = email.message_from_string(email_body)
    #^This is where the error occurs
    temp = m.store(emailid,'+FLAGS', '\\Seen')
    m.expunge()

    if mail.get_content_maintype() != 'multipart':
        continue

    #print "["+mail["From"]+"] :" + mail["Subject"]

   for part in mail.walk():
       if part.get_content_maintype() == 'multipart':
           continue
       if part.get('Content-Disposition') is None:
           continue

       filename = part.get_filename()
       att_path = os.path.join(detach_dir, filename)

       if not os.path.isfile(att_path) :
           fp = open(att_path, 'wb')
           fp.write(part.get_payload(decode=True))
           fp.close()

This is the error:

TypeError                                 Traceback (most recent call last)
<ipython-input-6-07c04531d5aa> in <module>()
      5     resp, data = m.fetch(emailid, "(RFC822)")
      6     email_body = data[0][1]
----> 7     mail = email.message_from_string(email_body)
      8     #This is where the error occurs
      9     temp = m.store(emailid,'+FLAGS', '\\Seen')

~\AppData\Local\Continuum\anaconda3\lib\email\__init__.py in message_from_string(s, *args, **kws)
     36     """
     37     from email.parser import Parser
---> 38     return Parser(*args, **kws).parsestr(s)
     39 
     40 def message_from_bytes(s, *args, **kws):

~\AppData\Local\Continuum\anaconda3\lib\email\parser.py in parsestr(self, text, headersonly)
     66         the file.
     67         """
---> 68         return self.parse(StringIO(text), headersonly=headersonly)
     69 
     70 

TypeError: initial_value must be str or None, not bytes

The code works fine when I tested it for a different subject, so I assume there's one email or attachment that's screwing it up. Reducing the search to emails sent on Jan 1 onwards might do the trick, but I don't know how to manipulate the search for two parameters:

typ, msgs = mails.search(None, '(SUBJECT "Daily Report")', 'SENTSINCE 01-JAN-2018')

Upvotes: 0

Views: 2374

Answers (1)

Petr Vala
Petr Vala

Reputation: 11

Change the line to: mail = email.message_from_bytes(email_body)

Upvotes: 1

Related Questions