Найти - Пользователи
Полная версия: Проблема с кодировкой между Python и outlook
Начало » Python для новичков » Проблема с кодировкой между Python и outlook
1
rufus
Добрый день.
Только начал осваивать язык, коллега написал для меня скрипт, который ходит на почтовый ящик и смотрит письма по теме, если тема совпадает, выводит в файл 1, если нет 0.
При попытке найти слово “test”, всё работает, но используя кириллицу “тест” он не видит письма. Хотя письмо с такой темой явно присутствует. Насколько я понимаю, проблема с кодировкой, перечитал много информации но не нашел ответа. Может кто то подсказать как исправить? Почта насколько я понимаю используется Exchange Server 2016

#!/usr/bin/env python3

import email
import imaplib
import os
import re

FindTheme=r'тест'
PachFile=“/etc/zabbix/scripts/ReadMail/ARM_KBR_result.TXT”
Flag=“0”

connect=imaplib.IMAP4(“nmail.имя.ru”,port=143)
connect.login(“имя ящика”, ‘пароль’)
connect.select(“INBOX”)
typ,data = connect.search(None, “All”)
for i in data.split():
typ,data=connect.fetch(i, “(RFC822)”)
msg = email.message_from_bytes(data)
if(FindTheme in msg):
Flag=“1”
else:
Flag=“0”


with open(PachFile, ‘wt’ ) as F:
F.write(Flag)

connect.logout()



Вот в таком ввиде тема отображается : Subject: =?koi8-r?B?1MXT1A==?=
А темы которые написаны на латинице : Subject: test
py.user.next
rufus
Вот в таком ввиде тема отображается : Subject: =?koi8-r?B?1MXT1A==?=
А темы которые написаны на латинице : Subject: test
Я думаю, ты попал в настоящее приключение. Я когда-то этим занимался, там много всяких сюрпризов; особенно радуют ошибки в программах, которые не соблюдают разные RFC. По RFC должно быть вот так, например, а программа тебе присылает какую-то ерунду самодельную, выдуманную из головы какой-то. Так что приготовься к тому, что заголовки у писем будут некорректными. А когда они некорректные, модуль питона, который умеет раскодировать заголовки, ожидает от тебя корректные заголовки. И когда он получает некорректные заголовки, он их просто оставляет нераскодированными, хотя он умеет раскодировать. Просто вот так случается.

Мне для этого пришлось тогда писать функцию высотой с небоскрёб примерно. Пришлось также обкладывать её всю юнит-тестами, потому что где было одно нарушение правил RFC и я его исправлял, появлялось какое-нибудь ещё нарушение, которое тоже надо было исправлять. Дикие письма - это целая галактика. Из-за этого приходилось ещё переделывать эту огромную функцию 100500 раз, для чего и понадобились мне юнит-тесты - когда под новое переделываешь её, может старое сломаться, что работало до этого.

Вот тебе направление
  
>>> import email.header
>>> 
>>> email.header.decode_header('Subject: =?koi8-r?B?1MXT1A==?=')
[(b'Subject: ', None), (b'\xd4\xc5\xd3\xd4', 'koi8-r')]
>>> 
>>> t = email.header.decode_header('Subject: =?koi8-r?B?1MXT1A==?=')[1]
>>> t[0].decode(t[1])
'тест'
>>>
Но это далеко не всё, что придётся делать.
rufus
py.user.next
Спасибо за ответ, я честно говоря не собирался в приключение, мне бы только зайти/выйти))). Для моих задач будет достаточно просто перевод из koi8-r в UTF-8, при этом я заранее буду знать какая тема будет, что в ней будет написано.
Я настолько не сведущ, что не могу найти применение вашему коду, хотя покрутил его уже достаточно.
Читал на форумах что сначала нужно разбить на биты а потом пересобрать в другой кодировке, это у меня получилось сделать только в примере, вышло примерно как и у вас “b'\xd4\xc5\xd3\xd4'” , что делать дальше с этим добром, не могу понять, декодироваться в UTF-8 оно не хочет….
py.user.next
Вот пример письма
  
>>> import email
>>> 
>>> text = """\
... From: =?koi8-r?B?1MXT1A==?= <from_abc@def>
... To: =?koi8-r?B?1MXT1A==?= <to_ghi@jkl>
... Subject: =?koi8-r?B?1MXT1A==?= subject
... mno body
... """
>>> 
>>> msg = email.message_from_string(text)
>>> 
>>> msg.get('from')
'=?koi8-r?B?1MXT1A==?= <from_abc@def>'
>>> 
>>> msg.get('to')
'=?koi8-r?B?1MXT1A==?= <to_ghi@jkl>'
>>> 
>>> msg.get('subject')
'=?koi8-r?B?1MXT1A==?= subject'
>>> 
>>> msg.get_payload()
'mno body\n'
>>>
Если ты думаешь, что в письмах только темы могут быть закодированы, то ты глубоко заблуждаешься. Там не только могут быть закодированы разные заголовки, так ещё и один заголовок запросто может быть частично закодированным, частично незакодированным, частично закодирован в одну кодировку, частично закодирован в другую кодировку и ещё заголовок может быть закодирован отправителем в неправильную кодировку без указания названия этой кодировки. И всё это одновременно в одном заголовке может быть. Сюрпризов там много бывает.

rufus
Для моих задач будет достаточно просто перевод из koi8-r в UTF-8
Тебе придётся брать каждый заголовок, потом этот заголовок ещё разделять на незакодированные части и закодированные части, потом раскодировать закодированные части, а потом соединять этот заголовок обратно, чтобы получать заголовок из незакодированных частей и раскодированных частей. Конечный заголовок будет представлен в Unicode, который можно потом закодировать для хранения в UTF-8.

rufus
Читал на форумах что сначала нужно разбить на биты а потом пересобрать в другой кодировке, это у меня получилось сделать только в примере, вышло примерно как и у вас “b'\xd4\xc5\xd3\xd4'” , что делать дальше с этим добром, не могу понять, декодироваться в UTF-8 оно не хочет….
Видно, что ты ещё и в кодировках не смыслишь ничего
  
>>> b'\xd4\xc5\xd3\xd4'.decode('koi8-r')
'тест'
>>>
Наверняка ты ещё и не знаешь, что такое Unicode.

После раскодирования строки в питоне, она представлена в виде символов Unicode. У них нет кодировки вообще. Для сохранения в файл строки в питоне, нужно при открытии файла указать кодировку, в которой всё будет сохраняться в файл.
  
with open('file.txt', 'w', encoding='utf-8') as fout:
    print('тест1', file=fout)
    fout.write('тест2')
Строки тест1 и тест2, используемые в коде на питоне, не закодированы; они представляют из себя последовательности Unicode-символов. В Unicode находятся все символы мира. Кодировка UTF-8 может закодировать любой символ из Unicode. Про кодировки тебе придётся ещё прочитать всю теорию, потому что в двух словах её не расскажешь, а сам ты не догадаешься до неё, потому что она обширная. Но сложного в ней ничего нет.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB