2011-08-23 8 views
10

Bir thunderbird mbox dosyasından gelen e-posta iletilerinin gövdesini ayıklamak için Python 3'ü kullanmaya çalışıyorum. Bu bir IMAP hesabıdır.Bir e-postanın gövdesini mbox dosyasından ayıklayarak, Charset ve Content Transfer Encoding'den bağımsız olarak düz metne çözme

Unicode dizesi olarak işlenebilecek e-postanın gövdesinin bir kısmını metin olarak almak istiyorum. E-postanın Thunderbird'de görünmesi ve \ r \ n = 20 vb. Gibi kaçmamış karakterler içermemesi gerekir.

Sanırım kod çözmeyi bilmediğim İçerik Aktarım Kodlamaları Kaldır. Çeşitli farklı İçerik Türlerine ve farklı İçerik Aktarım Kodlamalarına sahip e-postalar alıyorum. Bu benim şimdiki girişimdir:

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) 

Ama bu başarısız:

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

. get_payload() byte'ları döndürmeli, ancak Python 3'ün altından str, "decode = True" değerini geçmedikçe, bunu yapmazsınız. –

+0

Sadece decode = True ile denedim, bu da bayt döndürüyor ve bu yüzden bir hata yok. Kod çözme işlemi yapıldı gibi görünüyor ve şimdi tek yapmam gereken baytları dizelere dönüştürmektir. Yine de, çok çeşitli içerik kodlaması olan e-postalarla test etmedim. – dcb

+0

Huh, bu bir hata gibi görünüyor, başka bir şekilde olmalı, decode = True, str ve decode = False bytes döndürmelidir. :-) –

cevap

17

İşte iş yapar bazı kodu yerine o başarısız olur bu mesajlar için çökmesini hataları yazdırır. Umarım yararlı olabilir. Python 3'te bir hata varsa ve bu da düzeltilmişse, o zaman .get_payload (decode = True) satırlarının bir bayt nesnesi yerine bir str nesnesini döndürebileceğini unutmayın. Bu kodu bugün 2.7.2'de ve Python 3.2.1'de çalıştırdım.

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

Bu komut dosyası doğru tüm iletileri döndürmek için görünüyor: ACD gelen

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 

Eski cevap genellikle gerçek mesajın sadece bazı altbilgi döndürür. (en azından ben bu araç için açıyorum Gmane eposta messagens içinde : https://pypi.python.org/pypi/gmane )

şerefe

garip
İlgili konular