2015-06-18 119 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ñ