Как обрабатывать Python 3.x UnicodeDecodeError в пакете электронной почты?

Я пытаюсь прочитать письмо из файла, например так:

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 продолжить там, где произошло исключение.

Что я могу сделать?

4 ответа

Решение

Я не могу проверить ваше сообщение, поэтому я не знаю, сработает ли это на самом деле, но вы можете самостоятельно выполнить расшифровку строки:

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 мое предположение.

Чтобы разобрать сообщение электронной почты в Python 3 без ошибок Unicode, прочитайте файл в двоичном режиме и используйте email.message_from_binary_file(f) (или же email.message_from_bytes(f.read())) метод для анализа содержимого (см. документацию модуля email.parser).

Вот код, который анализирует сообщение способом, совместимым с 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)

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

Я сомневаюсь, что это лучший способ справиться с этим... но это по крайней мере способ...

Метод, который работает на 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 в то время как доступно другое кодирование, отсюда и небольшое обнаружение кодирования

Другие вопросы по тегам