【问题标题】:How to handle Python 3.x UnicodeDecodeError in Email package?如何处理电子邮件包中的 Python 3.x UnicodeDecodeError?
【发布时间】:2013-04-26 22:22:53
【问题描述】:

我尝试从文件中读取电子邮件,如下所示:

import email
with open("xxx.eml") as f:
   msg = email.message_from_file(f)

我得到这个错误:

Traceback (most recent call last):
  File "I:\fakt\real\maildecode.py", line 53, in <module>
    main()
  File "I:\fakt\real\maildecode.py", line 50, in main
    decode_file(infile, outfile)
  File "I:\fakt\real\maildecode.py", line 30, in decode_file
    msg = email.message_from_file(f)  #, policy=mypol
  File "C:\Python33\lib\email\__init__.py", line 56, in message_from_file
    return Parser(*args, **kws).parse(fp)
  File "C:\Python33\lib\email\parser.py", line 55, in parse
    data = fp.read(8192)
  File "C:\Python33\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 1920: character maps to <undefined>

该文件包含多部分电子邮件,其中部分以 UTF-8 编码。文件的内容或编码可能已损坏,但无论如何我都必须处理它。

如何读取文件,即使它有 Unicode 错误?我找不到策略对象compat32,似乎没有办法处理异常并让 Python 在异常发生的地方继续。

我能做什么?

【问题讨论】:

    标签: python exception unicode python-3.x python-unicode


    【解决方案1】:

    要在 Python 3 中解析电子邮件消息而不出现 unicode 错误,请以二进制模式读取文件并使用email.message_from_binary_file(f)(或email.message_from_bytes(f.read()))方法解析内容(请参阅documentation of the email.parser module)。

    以下代码以与 Python 2 和 3 兼容的方式解析消息:

    import email
    with open("xxx.eml", "rb") as f:
        try:
            msg = email.message_from_binary_file(f)  # Python 3
        except AttributeError:
            msg = email.message_from_file(f)  # Python 2
    

    (使用 Python 2.7.13 和 Python 3.6.0 测试)

    【讨论】:

      【解决方案2】:

      我无法测试您的消息,所以我不知道这是否真的有效,但您可以自己进行字符串解码:

      with open("xxx.eml", encoding='utf-8', errors='replace') as f:
          text = f.read()
          msg = email.message_from_string(f)
      

      如果消息实际上不是 UTF-8 格式,这将为您提供大量替换字符。但如果里面有\x81,我猜是UTF-8。

      【讨论】:

        【解决方案3】:
        with open('email.txt','rb') as f:
             ascii_txt = f.read().encode('ascii','backslashreplace')
        
        with open('email.txt','w') as f:
             f.write(ascii_text)
        
        #now do your processing stuff
        

        我怀疑这是处理这个问题的最佳方式......但它至少是一种方式......

        【讨论】:

        • 嗯 - 但我想用电子邮件包处理它,而不是本身销毁所有 UTF-8 或它所在的任何字符集。
        • 试试 encode ('utf-8',"ignore") ...也许吧?而不是('ascii')。但您需要打开文件以使用“wb”写入
        【解决方案4】:

        一种适用于 python 3 的方法,它找到编码并重新加载正确的编码。

        msg=email.message_from_file(open('file.eml',  errors='replace'))
        codes=[x for x in msg.get_charsets() if x!=None]
        if len(codes)>=1 : 
            msg=email.message_from_file(open('file.eml', encoding=codes[0]))
        

        我尝试过使用msg.get_charset(),但有时它会在另一种编码可用时回答None,因此编码检测稍微涉及

        【讨论】:

          猜你喜欢
          • 2021-12-02
          • 1970-01-01
          • 2015-05-20
          • 1970-01-01
          • 2011-05-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          相关资源
          最近更新 更多