Downloading multiple attachments using imaplib Downloading multiple attachments using imaplib python python

Downloading multiple attachments using imaplib


For any future python travellers.Here is a class that downloads any attachment found for an email and saves it to a specific location.

import emailimport imaplibimport osclass FetchEmail():    connection = None    error = None    def __init__(self, mail_server, username, password):        self.connection = imaplib.IMAP4_SSL(mail_server)        self.connection.login(username, password)        self.connection.select(readonly=False) # so we can mark mails as read    def close_connection(self):        """        Close the connection to the IMAP server        """        self.connection.close()    def save_attachment(self, msg, download_folder="/tmp"):        """        Given a message, save its attachments to the specified        download folder (default is /tmp)        return: file path to attachment        """        att_path = "No attachment found."        for part in msg.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(download_folder, filename)            if not os.path.isfile(att_path):                fp = open(att_path, 'wb')                fp.write(part.get_payload(decode=True))                fp.close()        return att_path    def fetch_unread_messages(self):        """        Retrieve unread messages        """        emails = []        (result, messages) = self.connection.search(None, 'UnSeen')        if result == "OK":            for message in messages[0].split(' '):                try:                     ret, data = self.connection.fetch(message,'(RFC822)')                except:                    print "No new emails to read."                    self.close_connection()                    exit()                msg = email.message_from_bytes(data[0][1])                if isinstance(msg, str) == False:                    emails.append(msg)                response, data = self.connection.store(message, '+FLAGS','\\Seen')            return emails        self.error = "Failed to retreive emails."        return emails    def parse_email_address(self, email_address):        """        Helper function to parse out the email address from the message        return: tuple (name, address). Eg. ('John Doe', 'jdoe@example.com')        """        return email.utils.parseaddr(email_address)


I reworked the code, breaking it up into functions. I use PEEK so I don't change the UNREAD status of the email messages.

I'm posting my take on the problem, similar to @John, but I use only functions instead of classes:

import imaplibimport email# Connect to an IMAP serverdef connect(server, user, password):    m = imaplib.IMAP4_SSL(server)    m.login(user, password)    m.select()    return m# Download all attachment files for a given emaildef downloaAttachmentsInEmail(m, emailid, outputdir):    resp, data = m.fetch(emailid, "(BODY.PEEK[])")    email_body = data[0][1]    mail = email.message_from_string(email_body)    if mail.get_content_maintype() != 'multipart':        return    for part in mail.walk():        if part.get_content_maintype() != 'multipart' and part.get('Content-Disposition') is not None:            open(outputdir + '/' + part.get_filename(), 'wb').write(part.get_payload(decode=True))# Download all the attachment files for all emails in the inbox.def downloadAllAttachmentsInInbox(server, user, password, outputdir):    m = connect(server, user, password)    resp, items = m.search(None, "(ALL)")    items = items[0].split()    for emailid in items:        downloaAttachmentsInEmail(m, emailid, outputdir)


You code appears okay except for the return (perhaps a typo?) right after the fp.close():

...fp.write(part.get_payload(decode=True))fp.close()return HttpResponse('check folder')

After saving the first attachment it returns from the function. Comment out that line and see if it fixes your issue.