【发布时间】:2015-06-18 06:10:39
【问题描述】:
我借用以下代码来解析电子邮件标头,并进一步添加标头。诚然,我并不完全理解所有关于应该直接使用 email.Headers 模块的脚手架的原因。
值得注意的是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 字符时,我得到:
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 的顶部添加 # -- coding: utf-8 --
- 在将
val传递给decode_header()之前调用unicode() - 在将
val传递给decode_header()之前调用.encode('utf-8') - 在将
val传递给decode_header()之前调用.encode('ISO-8859-1')
对上述任何一项都不满意。这是什么原因?鉴于我希望保持上述 email.Header 的用法(直接实例化 Header not),我们如何确保非 ASCII 字符被 decode_header 成功解码?
【问题讨论】:
-
当您提供的示例难以运行时,尝试提供帮助会有点令人反感。您可能想查看 stackoverflow.com/help/mcve 。我会跳入并四处游荡以体验问题并尝试解决它来接近它。但是......需要一个比这更多的 MCVE 才能开始。
-
@GreenAsJade 公平点。然而,要包含其余代码以及调用的其他模块,只是为了让它运行,我们需要数百行代码。我原以为 Python 专家能够仅通过代码审查就能查明错误。就像我说的那样,我尝试了各种方法(见上文)并研究了其他几篇关于 email.Header 和编码/编码的 SO 帖子,但无济于事。
-
@GreenAsJade 以下是完整代码的链接:old.zderadicka.eu/mailexp.py 为了重现该问题,您需要拥有(或创建)一封电子邮件,其中至少有一个包含字符的标题像ä。
-
问题是您要求我们做工作,所以您不必这样做。如果你让帮助者更容易自己做尽可能多的工作,你通常会得到更好的帮助。通常,您会发现,如果您自己编写一个导致问题的简单示例,您就会找到解决方案。如果你不这样做,那么它至少对我们来说很容易。发布整个代码的链接通常是没有用的,因为一大块代码并不明显如何运行。您需要的是一个将 unicode 传递给 decode_header 的小示例,与其他不相关的代码分开。
-
这看起来像是针对此问题的 MCVE。它假设你可以将任何你喜欢的东西传递给
decode_headers()。import email.Header print email.Header.decode_header("a") print email.Header.decode_header(u'\xe4')
标签: python unicode utf-8 character-encoding non-ascii-characters