2012-12-01 103 views
12

我試圖從一個可能包含一些大附件(約30MB)的Gmail帳戶獲取所有郵件。我只需要名稱,而不是整個文件。我發現了一段代碼得到一個消息和附件的名字,但它下載的文件,然後讀取它的名字:獲取Gmail附件文件名而不下載它

import imaplib, email 

#log in and select the inbox 
mail = imaplib.IMAP4_SSL('imap.gmail.com') 
mail.login('username', 'password') 
mail.select('inbox') 

#get uids of all messages 
result, data = mail.uid('search', None, 'ALL') 
uids = data[0].split() 

#read the lastest message 
result, data = mail.uid('fetch', uids[-1], '(RFC822)') 
m = email.message_from_string(data[0][1]) 

if m.get_content_maintype() == 'multipart': #multipart messages only 
    for part in m.walk(): 
     #find the attachment part 
     if part.get_content_maintype() == 'multipart': continue 
     if part.get('Content-Disposition') is None: continue 

     #save the attachment in the program directory 
     filename = part.get_filename() 
     fp = open(filename, 'wb') 
     fp.write(part.get_payload(decode=True)) 
     fp.close() 
     print '%s saved!' % filename 

我必須這樣做一分鐘一次,所以我不能下載數MB數據。我是網頁腳本的新手,所以任何人都可以幫助我?我實際上並不需要使用imaplib,任何python lib都可以。

問候

+0

你可以發送只有20MB的Gmail你知道嗎? – 0x90

+0

我的意思是所有消息中的所有附件。 – mopsiok

回答

8

而不是取RFC822,這是全部內容,可以指定BODYSTRUCTURE

來自imaplib的結果數據結構很混亂,但您應該能夠在不下載整個文件的情況下查找消息每個部分的文件名,內容類型和大小。

+0

這就是我一直在尋找...結果是真正令人困惑,但它的工作原理。非常感謝! – mopsiok

+0

這正是我正在尋找的東西。但是,有沒有關於如何分析那個瘋狂的結果字符串的線索? @mopsiok,你是怎麼處理它的? – jjon

+1

我已經做了一些測試,但結果不是很好。事實上,我發現獲取附件列表對我的應用來說是相當不足的。最終,我會通過傳遞所有郵件內容,獲取文本和所有附件。我沒有解析代碼,因爲我說這是無效的。抱歉... – mopsiok

3

如果你知道一些有關的文件名,你可以使用X-GM-RAW gmail extensions for imap SEARCH command。這些擴展可讓您使用任何gmail advanced search查詢來過濾消息。通過這種方式,您可以將下載限制爲匹配的消息,或者排除一些您不需要的消息。

mail.uid('search', None, 'X-GM-RAW', 
     'has:attachment filename:pdf in:inbox -label:parsed')) 

以上搜索的INBOX中帶有PDF附件的郵件未標記爲「已解析」。

一些專業提示:

  • 標籤的郵件,你已經被解析,所以你不需要再次讀取他們(-label:在上面的例子中解析過濾器)
  • 始終使用uid版本,而不是標準的順序標識(你已經這樣做)
  • 不幸的是,MIME很麻煩:有很多客戶端奇怪(或錯誤)的東西。你可以嘗試下載和解析頭文件,但這是否值得麻煩?

[編輯]

如果你分析它之後標記一個消息,你可以跳過你已經被解析的消息。這應該足夠合理來監視您的課堂郵箱。

也許你生活在互聯網帶寬比程序員時間更昂貴的世界角落;在這種情況下,您只能獲取標題並查找「Content-disposition」==「attachment; filename = somefilename.ext」。

+0

這很酷,但問題是我對附件一無所知。我正在編寫一個腳本來「掃描」我班級帳戶的所有Gmail收件箱,並告訴我它是否是新內容,包括有關附件(名稱和大小)的信息。 搜索未讀郵件將不起作用,因爲該帳戶已被30人使用。 – mopsiok

+0

至少可以跳過沒有附件和已經解析的消息的消息;請注意,您也可以按尺寸過濾。 –

+0

當然,我可以,但跳過已解析的消息沒有問題。問題在於在一分鐘內解析接下來的20條內容爲20MB的附件。 – mopsiok

2

RFC822消息數據項的FETCH在功能上等效於BODY[]。 IMAP4支持其他消息數據項,列在section 6.4.5 of RFC 3501中。

嘗試請求一組不同的消息數據項以獲取所需的信息。例如,您可以嘗試RFC822.HEADERBODY.PEEK[MIME]

0

老問題,但只是想分享我今天想出的解決方案。搜索包含附件的所有電子郵件,並輸出uid,發件人,主題和格式化的附件列表。編輯相關的代碼,以顯示如何格式化BODYSTRUCTURE:

data = mailobj.uid('fetch', mail_uid, '(BODYSTRUCTURE)')[1] 
    struct = data[0].split()   
    list = []      #holds list of attachment filenames 

    for j, k in enumerate(struct): 
     if k == '("FILENAME"': 
      count = 1 
      val = struct[j + count] 
      while val[-3] != '"': 
       count += 1 
       val += " " + struct[j + count] 
      list.append(val[1:-3]) 
     elif k == '"FILENAME"': 
      count = 1 
      val = struct[j + count] 
      while val[-1] != '"': 
       count += 1 
       val += " " + struct[j + count] 
      list.append(val[1:-1]) 

我也它公佈了GitHub