2011-06-03 105 views
16

如何使用imaplib從單個郵件下載多個附件?使用imaplib下載多個附件

假設我有一封電子郵件,並且該電子郵件包含4個附件。我怎樣才能下載所有這些附件?下面的代碼只從電子郵件下載一個附件。

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') 

回答

5

您代碼出現除了return沒關係的fp.close()之後(也許是筆誤?):

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

將其保存在函數返回第一附後。註釋掉該行,看看它是否解決了你的問題。

2
* 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) 
22

對於任何未來的python旅客。 這是一個類,它下載爲電子郵件找到的任何附件並將其保存到特定位置。

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_string(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) 
8

我修改了代碼,將其分成功能。我使用PEEK,所以我不更改電子郵件的UNREAD狀態。

我張貼我拿的問題,類似@約翰,但我只用函數替代類:

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)