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