2011-11-29 34 views
2

我試圖保存來自Google郵件帳戶的電子郵件附件。保存電子郵件附件(python3,pop3_ssl,gmail)

AFAIK,這是可以做到「走」的消息,並獲取其有效載荷,

for part in message.walk(): 
    # getting payload, saving attach etc. 

,但它不工作。 請參見下面的整個例子:

def test_save_attach(self): 
    self.connection = poplib.POP3_SSL('pop.gmail.com', 995) 
    self.connection.set_debuglevel(1) 
    self.connection.user(USERNAME) 
    self.connection.pass_(PASS) 

    emails, total_bytes = self.connection.stat() 
    print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes)) 
    # return in format: (response, ['mesg_num octets', ...], octets) 
    msg_list = self.connection.list() 
    print(msg_list) 

    # messages processing 
    for i in range(emails): 
     response = self.connection.retr(i+1) 
     # return in format: (response, ['line', ...], octets) 
     lines = response[1] 
     str_message = email.message_from_bytes(b''.join(lines)) 
     print(str_message) 

     # save attach 
     for part in str_message.walk(): 
      print(part.get_content_type()) 

      if part.get_content_maintype() == 'multipart': 
       continue 

      if part.get('Content-Disposition') is None: 
       continue 

      filename = part.get_filename() 
      if not(filename): continue 

      fp = open(os.path.join(self.savedir, filename), 'wb') 
      fp.write(part.get_payload(decode=1)) 
      fp.close 

    self.connection.quit() 

腳本輸出是:

*cmd* 'USER **********' 
*cmd* 'PASS **********' 
*cmd* 'STAT' 
*stat* [b'+OK', b'1', b'5301'] 
1 emails in the inbox, 5301 bytes total 
*cmd* 'LIST' 
(b'+OK 1 messages (5301 bytes)', [b'1 5301'], 8) 
*cmd* 'RETR 1' 
[<message headers and body>] 
text/plain 
*cmd* 'QUIT' 

正如我們所看到的,該消息的唯一的部分具有「text/plain的」格式和不包含任何附加信息,儘管消息體確實包含了它,並且可以在調試輸出時看到它。

回答

7
response = self.connection.retr(i+1) 
raw_message = response[1] 

raw_message不是字符串。 retr以單行列表形式返回消息。你試圖將列表轉換成一個字符串str(raw_message) - 這是行不通的。

代替,加入這些線在一起,例如,更換

str_message = email.message_from_string(str(raw_message)) 

有:

python2:

str_message = email.message_from_string("\n".join(raw_message)) 

python3:

str_message = email.message_from_bytes(b'\n'.join(raw_message)) 

編輯://加入我的全部工作的源和輸出幫助調試問題

import poplib 
import email 
import os 

class GmailTest(object): 
    def __init__(self): 
     self.savedir="/tmp" 

    def test_save_attach(self): 
     self.connection = poplib.POP3_SSL('pop.gmail.com', 995) 
     self.connection.set_debuglevel(1) 
     self.connection.user("<munged>") 
     self.connection.pass_("<munged>") 

     emails, total_bytes = self.connection.stat() 
     print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes)) 
     # return in format: (response, ['mesg_num octets', ...], octets) 
     msg_list = self.connection.list() 
     print(msg_list) 

     # messages processing 
     for i in range(emails): 

      # return in format: (response, ['line', ...], octets) 
      response = self.connection.retr(i+1) 
      raw_message = response[1] 

      str_message = email.message_from_bytes(b'\n'.join(raw_message)) 

      # save attach 
      for part in str_message.walk(): 
       print(part.get_content_type()) 

       if part.get_content_maintype() == 'multipart': 
        continue 

       if part.get('Content-Disposition') is None: 
        print("no content dispo") 
        continue 

       filename = part.get_filename() 
       if not(filename): filename = "test.txt" 
       print(filename) 

       fp = open(os.path.join(self.savedir, filename), 'wb') 
       fp.write(part.get_payload(decode=1)) 
       fp.close 

     #I exit here instead of pop3lib quit to make sure the message doesn't get removed in gmail 
     import sys 
     sys.exit(0) 

d=GmailTest() 
d.test_save_attach() 

輸出:

python3 thetest.py 
*cmd* 'USER <munged>' 
*cmd* 'PASS <munged>' 
*cmd* 'STAT' 
*stat* [b'+OK', b'2', b'152928'] 
2 emails in the inbox, 152928 bytes total 
*cmd* 'LIST' 
(b'+OK 2 messages (152928 bytes)', [b'1 76469', b'2 76459'], 18) 
*cmd* 'RETR 1' 
multipart/mixed 
text/plain 
test.txt 
application/pdf 
ADDFILE_0.pdf 
*cmd* 'RETR 2' 
multipart/mixed 
text/plain 
test.txt 
application/pdf 
ADDFILE_0.pdf 
+0

我明白了,但此行似乎有「字節」的類型,所以串.join()不起作用。如果我這樣做 \t線=響應[1] \t MESSAGE_TEXT = 「」 \t線路在線路: \t \t MESSAGE_TEXT + = STR(線) 我得到同樣的效果 –

+0

啊,你似乎使用python3,我不熟悉(尚未),對不起!您可能需要連接字節,然後使用email.message_from_bytes(這是python 3 afaik中的新增功能) - 但這只是一個猜測 – Gryphius

+0

使用email.message_from_bytes()會得到相同的結果。 –