python email imap attachment

python - Descargando mĂșltiples archivos adjuntos usando imaplib



email attachment (4)

¿Cómo puedo descargar varios archivos adjuntos de un solo correo usando imaplib ?

Digamos que tengo un correo electrónico y ese correo electrónico contiene 4 archivos adjuntos. ¿Cómo puedo descargar todos esos archivos adjuntos? El siguiente código solo descarga un archivo adjunto de un correo electrónico.

detach_dir = ''c:/downloads'' m = imaplib.IMAP4_SSL("imap.gmail.com") m.login(''[email protected]'',''3323434'') m.select("[Gmail]/All Mail") resp, items = m.search(None, "(UNSEEN)") 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) 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() return HttpResponse(''check folder'')


Para cualquier futuro viajero pitón. Aquí hay una clase que descarga cualquier archivo adjunto encontrado para un correo electrónico y lo guarda en una ubicación específica.

import email import imaplib import os class 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'', ''[email protected]'') """ return email.utils.parseaddr(email_address)


Reelaboré el código, dividiéndolo en funciones. Uso PEEK para no cambiar el estado de UNREAD de los mensajes de correo electrónico.

Estoy publicando mi opinión sobre el problema, similar a @John, pero solo uso funciones en lugar de clases:

import imaplib import email # Connect to an IMAP server def connect(server, user, password): m = imaplib.IMAP4_SSL(server) m.login(user, password) m.select() return m # Download all attachment files for a given email def 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)


Su código parece correcto, excepto por la return (¿quizás un error tipográfico?) Justo después de fp.close() :

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

Después de guardar el primer archivo adjunto, regresa de la función. Comente esa línea y vea si soluciona su problema.


* You can try following function to get mail attachment def create_message_attachment(self,msg_str): count = 1 body = '''' content_id = '''' for part in msg_str.walk(): file_name_gl = None mptype = part.get_content_maintype() file_name_gl = part.get_filename() if mptype == "multipart": continue elif mptype == "text": if not file_name_gl: continue elif mptype == "image": content_id = part.get(''Content-ID'') if not file_name_gl: file_name_gl = ''image_'' + str(count) + ''.'' + part.get_content_subtype() count = count + 1 body = part.get_payload(decode = True) if type(body) <> type(None) : body = body.strip() if body <> "": body = base64.encodestring(body)