2011-08-23 25 views
10

Tôi đang cố gắng sử dụng Python 3 để trích xuất nội dung thư email từ tệp mbox thunderbird. Đây là một tài khoản IMAP.Trích xuất nội dung của email từ tệp mbox, giải mã nó thành văn bản thuần túy bất kể Mã hóa chuyển mã và mã hóa

Tôi muốn có phần văn bản trong phần nội dung của email sẵn có để xử lý dưới dạng chuỗi unicode. Nó phải giống như 'email' trong Thunderbird và không chứa các ký tự thoát như \ r \ n = 20, v.v.

Tôi nghĩ rằng đó là Mã hóa chuyển nội dung mà tôi không biết cách giải mã hoặc tẩy. Tôi nhận được email với nhiều loại Nội dung khác nhau và Mã hóa Chuyển nội dung khác nhau. Đây là nỗ lực hiện tại của tôi:

import mailbox 
import quopri,base64 

def myconvert(encoded,ContentTransferEncoding): 
    if ContentTransferEncoding == 'quoted-printable': 
     result = quopri.decodestring(encoded) 
    elif ContentTransferEncoding == 'base64': 
     result = base64.b64decode(encoded) 

mboxfile = 'C:/Users/Username/Documents/Thunderbird/Data/profile/ImapMail/server.name/INBOX' 

for msg in mailbox.mbox(mboxfile): 
    if msg.is_multipart(): #Walk through the parts of the email to find the text body. 
     for part in msg.walk(): 
      if part.is_multipart(): # If part is multipart, walk through the subparts. 
       for subpart in part.walk(): 
        if subpart.get_content_type() == 'text/plain': 
         body = subpart.get_payload() # Get the subpart payload (i.e the message body) 
        for k,v in subpart.items(): 
          if k == 'Content-Transfer-Encoding': 
           cte = v    # Keep the Content Transfer Encoding 
      elif subpart.get_content_type() == 'text/plain': 
       body = part.get_payload()   # part isn't multipart Get the payload 
       for k,v in part.items(): 
        if k == 'Content-Transfer-Encoding': 
         cte = v      # Keep the Content Transfer Encoding 

print(body) 
print('Body is of type:',type(body)) 
body = myconvert(body,cte) 
print(body) 

Nhưng điều này không thành công với:

Body is of type: <class 'str'> 
Traceback (most recent call last): 
File "C:/Users/David/Documents/Python/test2.py", line 31, in <module> 
    body = myconvert(body,cte) 
File "C:/Users/David/Documents/Python/test2.py", line 6, in myconvert 
    result = quopri.decodestring(encoded) 
File "C:\Python32\lib\quopri.py", line 164, in decodestring 
    return a2b_qp(s, header=header) 
TypeError: 'str' does not support the buffer interface 
+0

Đó là lạ. get_payload() sẽ trả về byte, nhưng str theo Python 3, trừ khi bạn chuyển vào 'decode = True', mà bạn không làm. –

+0

Tôi vừa thử nó với decode = True, và nó trả về byte, và do đó không có lỗi. Dường như việc giải mã được thực hiện, và bây giờ tất cả những gì tôi cần làm là chuyển đổi byte thành chuỗi. Mặc dù tôi vẫn chưa thử nghiệm với các email có nhiều loại mã hóa nội dung. – dcb

+0

Huh, mà có vẻ như một lỗi, nó phải là cách khác xung quanh, giải mã = ​​True nên trả về str và giải mã = ​​False byte. :-) –

Trả lời

17

Dưới đây là một số mã mà không được công việc, nó in lỗi thay vì đâm cho những thông điệp mà nó sẽ thất bại. Tôi hy vọng rằng nó có thể hữu ích. Lưu ý rằng nếu có một lỗi trong Python 3, và đó là cố định, sau đó các dòng .get_payload (decode = True) sau đó có thể trả về một đối tượng str thay vì một đối tượng byte. Tôi chạy mã này ngày hôm nay trên 2.7.2 và trên Python 3.2.1.

import mailbox 

def getcharsets(msg): 
    charsets = set({}) 
    for c in msg.get_charsets(): 
     if c is not None: 
      charsets.update([c]) 
    return charsets 

def handleerror(errmsg, emailmsg,cs): 
    print() 
    print(errmsg) 
    print("This error occurred while decoding with ",cs," charset.") 
    print("These charsets were found in the one email.",getcharsets(emailmsg)) 
    print("This is the subject:",emailmsg['subject']) 
    print("This is the sender:",emailmsg['From']) 

def getbodyfromemail(msg): 
    body = None 
    #Walk through the parts of the email to find the text body.  
    if msg.is_multipart():  
     for part in msg.walk(): 

      # If part is multipart, walk through the subparts.    
      if part.is_multipart(): 

       for subpart in part.walk(): 
        if subpart.get_content_type() == 'text/plain': 
         # Get the subpart payload (i.e the message body) 
         body = subpart.get_payload(decode=True) 
         #charset = subpart.get_charset() 

      # Part isn't multipart so get the email body 
      elif part.get_content_type() == 'text/plain': 
       body = part.get_payload(decode=True) 
       #charset = part.get_charset() 

    # If this isn't a multi-part message then get the payload (i.e the message body) 
    elif msg.get_content_type() == 'text/plain': 
     body = msg.get_payload(decode=True) 

    # No checking done to match the charset with the correct part. 
    for charset in getcharsets(msg): 
     try: 
      body = body.decode(charset) 
     except UnicodeDecodeError: 
      handleerror("UnicodeDecodeError: encountered.",msg,charset) 
     except AttributeError: 
      handleerror("AttributeError: encountered" ,msg,charset) 
    return body  


#mboxfile = 'C:/Users/Username/Documents/Thunderbird/Data/profile/ImapMail/server.name/INBOX' 
print(mboxfile) 
for thisemail in mailbox.mbox(mboxfile): 
    body = getbodyfromemail(thisemail) 
    print(body[0:1000]) 
2

Kịch bản này dường như trả lại tất cả các thông điệp một cách chính xác:

def getcharsets(msg): 
    charsets = set({}) 
    for c in msg.get_charsets(): 
     if c is not None: 
      charsets.update([c]) 
    return charsets 

def getBody(msg): 
    while msg.is_multipart(): 
     msg=msg.get_payload()[0] 
    t=msg.get_payload(decode=True) 
    for charset in getcharsets(msg): 
     t=t.decode(charset) 
    return t 

Cựu câu trả lời từ ACD thường sẽ chỉ trả lại một số chân của thông điệp thực sự. ( ít nhất là trong messagens email GMANE Tôi mở cho hộp công cụ này: https://pypi.python.org/pypi/gmane )

cổ vũ

Các vấn đề liên quan