2015-06-18 163 views
-1

我借用下面的代碼來解析電子郵件標題,並且另外在下面添加一個標題。無可否認,我並不完全理解模塊應該直接使用的所有腳手架的原因。如何讓email.Header.decode_header使用非ASCII字符?

值得注意的是Headers未被實例化;而其decode_header函數被調用:

class DecodedHeader(object): 
    def __init__(self, s, folder): 
     self.msg=email.message_from_string(s[1]) 
     self.info=parseList(s[0]) 
     self.folder=folder 

    def __getitem__(self,name): 
     if name.lower()=='folder': return self.folder 
     elif name.lower()=='uid': return self.info[1][3] 
     elif name.lower()=='flags': return ','.join(self.info[1][1]) 
     elif name.lower()=='internal-date': 
      ds= self.info[1][5] 
      if Options.dateFormat: 
       ds= time.strftime(Options.dateFormat,imaplib.Internaldate2tuple('INTERNALDATE "'+ds+'"')) 
      return ds 
     elif name.lower()=='size': return self.info[1][7] 
     val= self.msg.__getitem__(name) 
     if val==None: return None 
     return self._convert(email.Header.decode_header(val),name) 
    def get(self,key,default=None): 
     return self.__getitem__(key) 

    def _convert(self, list, name): 
     l=[] 
     for s, encoding in list: 
      try:  
       if (encoding!=None): 
        s=unicode(s,encoding, 'replace').encode(Options.encoding,'replace') 
      except Exception, e: 
       print >>sys.stderr, "Encoding error", e 
      l.append(s) 

     res= "".join(l) 
     if Options.addr and name.lower() in ('from','to', 'cc', 'return-path','reply-to'): res=self._modifyAddr(res) 
     if Options.dateFormat and name.lower() in ('date'): res = self._formatDate(res) 
     return res 

這裏的問題:當頭部(VAL)中包含非ASCII字符,如A和A,我得到:

Traceback (most recent call last): 
    File "v12.py", line 434, in <module> 
    main() 
    File "v12.py", line 396, in main 
    writer.writerow(msg) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py", line 152, in writerow 
    return self.writer.writerow(self._dict_to_list(rowdict)) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py", line 149, in _dict_to_list 
    return [rowdict.get(key, self.restval) for key in self.fieldnames] 
    File "v12.py", line 198, in get 
    return self.__getitem__(key) 
    File "v12.py", line 196, in __getitem__ 
    return self._convert(email.Header.decode_header(val),name) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/header.py", line 76, in decode_header 
    header = str(header) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 1: ordinal not in range(128) 

其中u'\ XE4 '是ä。傳遞之前header.py的頂部上val

  • 調用的Unicode() - UTF-8 -:

    我試過幾件事情:

    • 添加# - - 編碼到decode_header()
    • 調用.encode上val( 'UTF-8')將其傳遞給decode_header()
    • 調用.encode( 'ISO-8859-1')上val它傳遞給decode_header()之前前

    沒有任何上述的喜悅。這裏的原因是什麼?鑑於我期待保持上述email.Header的使用(並且直接實例化頭部而不是),我們如何確保非ASCII字符被decode_header成功解碼?

  • +0

    這使得它有點offputting,試圖幫助時,您所提供的例子是難以運行。您可能想要查看http://stackoverflow.com/help/mcve。我會通過跳槽來解決問題並嘗試解決問題。但是......需要更多的MCVE才能開始。 – GreenAsJade

    +0

    @GreenAsJade公平點。然而,要包含代碼的其餘部分以及其他所謂的模塊,爲了讓它運行起來,我們需要數百行代碼。我原以爲Python大師能夠單獨查明代碼審查中的錯誤。就像我所說的,我已經嘗試了各種各樣的東西(參見上文),並研究了幾個其他的圍繞email.Header和編碼/編碼的SO帖子,但都無濟於事。 – Pyderman

    +0

    @GreenAsJade以下是完整代碼的鏈接:http://old.zderadicka.eu/mailexp。py爲了重現此問題,您需要擁有(或創建)至少包含一個包含像ä這樣的字符的標頭的電子郵件。 – Pyderman

    回答

    1

    標題必須被正確編碼才能被解碼。它看起來像val來自一個已經存在的消息,所以也許這個消息是不好的。該錯誤表明它是一個Unicode字符串,但它應該是該字符串。 Python幫助email.header中的例子很簡單。

    下面編碼兩個頭甚至不使用相同的編碼:

    >>> import email.header 
    >>> h = email.header.Header(u'To: Märk'.encode('iso-8859-1'),'iso-8859-1') 
    >>> h.append(u'From: Jòhñ'.encode('utf8'),'utf8') 
    >>> h 
    <email.header.Header instance at 0x00559F58> 
    >>> s = h.encode() 
    >>> s 
    '=?iso-8859-1?q?To=3A_M=E4rk?= =?utf-8?b?RnJvbTogSsOyaMOx?=' 
    

    注意,正確編碼頭是一個字節的字符串帶有嵌入式編碼名稱,它不使用非ASCII字符。

    這對其解碼:

    >>> email.header.decode_header(s) 
    [('To: M\xe4rk', 'iso-8859-1'), ('From: J\xc3\xb2h\xc3\xb1', 'utf-8')] 
    >>> d = email.header.decode_header(s) 
    >>> for s,e in d: 
    ... print s.decode(e) 
    ... 
    To: Märk 
    From: Jòhñ