Кроме того, в этом модуле применяется действующий в рамках сеанса прием декодирования байтов сообщений в строку Юникода, что необходимо для дальнейшего их анализа, о чем уже говорилось выше в этой главе. Для декодирования используется кодировка, определенная пользователем в модуле mailconfig, и эвристические алгоритмы. Так как декодирование выполняется немедленно, сразу после получения сообщения, все клиенты этого пакета могут быть уверены, что текст сообщения будет возвращен в виде строки Юникода str, и могут опираться на этот факт при выполнении дальнейших операций, включая анализ, отображение или сохранение. В дополнение к настройкам в модуле mailconfig выполняется также попытка угадать кодировку поочередным применением некоторых распространенных кодировок, хотя при этом вероятен вариант, когда при использовании параметров из mailconfig окажется невозможным сохранить в файл сообщение, декодированное с помощью угаданной кодировки.
Как уже говорилось, такой подход, когда настройки кодировки действуют в рамках всего сеанса, не является идеальным, но он может быть скорректирован в сеансе работы клиента и отражает текущие ограничения пакета email в Python 3.1 — механизм анализа в пакете принимает уже декодированные строки Юникода, а операции получения почты возвращают двоичные строки. Если декодировать сообщение не удалось, предпринимается попытка декодировать только заголовки в текст ASCII (или в другую распространенную кодировку) или в кодировку по умолчанию для данной платформы, а в тело письма вставляется сообщение об ошибке. Этот эвристический алгоритм делает все возможное, чтобы избежать аварийного завершения клиента из-за исключения (тест этой логики вы найдете в файле _test-decoding.py в пакете с примерами). На практике обычно бывает вполне достаточно 8-битовой кодировки, такой как Latin-1, потому что изначально стандарты электронной почты ограничивались только кодировкой ASCII.
В принципе, можно попробовать отыскать информацию о кодировке в заголовках сообщения, выполняя анализ письма по частям. В этом случае можно ограничить действие настроек кодировки при декодировании полного текста сообщения только текущим письмом, а не сеансом, и сопровождать каждое письмо своим именем кодировки для выполнения дальнейших операций, таких как сохранение. Однако это еще больше осложнит реализацию, так как для сообщений, сохраняемых в один файл, можно определить только одну (совместимую) кодировку, общую для всего файла, а не для каждого сообщения в отдельности. Кроме того, указанные в заголовках кодировки могут относиться лишь к отдельным компонентам, а не ко всему тексту сообщения. Поскольку большинство почтовых отправлений будут соответствовать 7- или 8-битовому стандартам и в будущих версиях пакета email эта проблема, скорее всего, будет решена, дополнительное усложнение может оказаться излишним.
Имейте также в виду, что здесь выполняется декодирование полного текста сообщения, получаемого с сервера. В действительности это лишь один из этапов на пути декодирования сообщений в современном мире Юникода. Кроме того:
• Содержимое анализируемых частей сообщений по-прежнему может возвращаться в виде строк байтов и требовать специальной обработки или дальнейшего декодирования в Юникод (смотрите модуль mailParser.py далее).
• Текстовые части и вложения также налагают определенные требования к кодированию при составлении сообщений (смотрите модуль mailSender.py выше).
• Для заголовков сообщений имеются собственные соглашения по кодированию, и интернационализированные заголовки могут быть закодированы с применением кодировки Юникода и преобразованы в формат MIME (смотрите модули mailParser.py и mailSender.py).
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011