email.policy: Объекты политики

Добавлено в версии 3.3.


Основное внимание в пакете email уделяется обработке сообщений электронной почты, в соответствии с различными документами RFC электронной почты и MIME. Однако общий формат сообщений электронной почты (блок полей заголовка, каждое состоящее из имени, затем следует двоеточие, за которым идёт значение, после всего блока следует пустая строка и произвольное «тело»), — это формат, нашедший применение за пределами области эл. адреса. Некоторые из данных применений довольно точно соответствуют основным RFC электронной почты, некоторые нет. Даже при работе с электронной почтой бывают случаи, когда желательно нарушить строгое соответствие RFC, например, создание электронных писем, взаимодействующие с почтовыми серверами не соответствующие стандартам, или реализация расширений, которые вы хотите использовать, с нарушением стандартов.

Объекты политики предоставляют пакету email гибкость для обработки всех данных разрозненных вариантов использования.

Объект Policy инкапсулирует множество атрибутов и методов, управляющих поведением различных компонентов пакета email во время использования. Экземпляры Policy можно передавать различным классам и методам в пакете email, чтобы изменить поведение по умолчанию. Устанавливаемые значения и их значения по умолчанию рассмотрены далее.

Существует политика по умолчанию, используемая всеми классами в пакете email. Для всех классов parser и связанных вспомогательных функций, а также для класса Message это политика Compat32 через соответствующий предопределенный экземпляр compat32. Данная политика обеспечивает полную обратную совместимость (в некоторых случаях, включая совместимость с ошибками) с версией пакета email, предшествующей Python3.3.

Значение по умолчанию для ключевого аргумента policy EmailMessage является политикой EmailPolicy через её предопределенный экземпляр default.

Когда создаётся объект Message или EmailMessage, он получает политику. Если сообщение создано с помощью parser, переданная синтаксическому анализатору политика, будет используемой созданным им сообщением политикой. Если сообщение создаётся программой, то политику можно указать при его создании. Когда сообщение передаётся generator, генератор по умолчанию использует политику из сообщения, но вы также можете передать генератору определенную политику, которая переопределит политику, хранящуюся в объекте сообщения.

Значение по умолчанию для ключевого аргумента policy для классов email.parser и вспомогательных функций парсера будет меняться в будущей версии Python. Поэтому вы должны всегда явно указывайте, какую политику вы хотите использовать при вызове любого из классов и функций, реализованных в модуле parser.

В первой части данной документации рассматриваются функции Policy, абстрактный базовый класс, определяющие функции, общие для всех объектов политики, включая compat32. Это включает в себя определённые вызываемые внутри пакета email методы перехвата, которые пользовательская политика может переопределить для получения другого поведения. Во второй части рассматриваются конкретные классы EmailPolicy и Compat32, которые реализуют хуки, обеспечивающие стандартное поведение и соответственно обратно совместимое поведение и функции.

Экземпляры Policy являются неизменяемыми, но их можно клонировать, принимая те же ключевые аргументы, что и конструктор класса, и возвращая новый экземпляр Policy, являющийся копией оригинала, но с измененными значениями указанных атрибутов.

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

>>> from email import message_from_binary_file
>>> from email.generator import BytesGenerator
>>> from email import policy
>>> from subprocess import Popen, PIPE
>>> with open('mymsg.txt', 'rb') as f:
...     msg = message_from_binary_file(f, policy=policy.default)
>>> p = Popen(['sendmail', msg['To'].addresses[0]], stdin=PIPE)
>>> g = BytesGenerator(p.stdin, policy=msg.policy.clone(linesep='\r\n'))
>>> g.flatten(msg)
>>> p.stdin.close()
>>> rc = p.wait()

Здесь мы говорим BytesGenerator использовать правильные символы разделителя строк RFC при создании двоичной строки для передачи в sendmail's stdin, где политика по умолчанию будет использовать разделители строк \n.

Некоторые методы пакета email принимают ключевой аргумент policy, что позволяет переопределить политику для этого метода. Например, следующий код использует метод as_bytes() объекта msg из предыдущего примера и записывает сообщение в файл, используя собственные разделители строк для платформы, на которой он выполняется:

>>> import os
>>> with open('converted.txt', 'wb') as f:
...     f.write(msg.as_bytes(policy=msg.policy.clone(linesep=os.linesep)))
17

Объекты политики также можно комбинировать с помощью оператора сложения, создавая объект политики, параметры которого представляют собой комбинацию нестандартных значений суммируемых объектов:

>>> compat_SMTP = policy.compat32.clone(linesep='\r\n')
>>> compat_strict = policy.compat32.clone(raise_on_defect=True)
>>> compat_strict_SMTP = compat_SMTP + compat_strict

Эта операция не коммутативна; т. е. порядок, в котором добавляются объекты, имеет значение. Пример:

>>> policy100 = policy.compat32.clone(max_line_length=100)
>>> policy80 = policy.compat32.clone(max_line_length=80)
>>> apolicy = policy100 + policy80
>>> apolicy.max_line_length
80
>>> apolicy = policy80 + policy100
>>> apolicy.max_line_length
100
class email.policy.Policy(**kw)

Абстрактный базовый класс для всех классов политик. Он предоставляет реализации по умолчанию для нескольких тривиальных методов, а также реализацию свойства неизменности, метод clone() и семантику конструктора.

Конструктору класса политики можно передавать различные ключевые аргументы. Аргументы, которые могут быть указаны, — это любые свойства, не относящиеся к методу, в этом классе, а также любые дополнительные свойства, не относящиеся к методу, в конкретном классе. Значение, указанное в конструкторе, переопределит значение по умолчанию для соответствующего атрибута.

Данный класс определяет следующие свойства, и поэтому значения для следующих могут быть переданы в конструкторе любого класса политики:

max_line_length

Максимальная длина любой строки в сериализованном выводе, не считая символов конца строки. По умолчанию 78, согласно RFC 5322. Значение 0 или None указывает на то, что вообще не следует выполнять перенос строк.

linesep

Строка, которая будет использоваться для завершения строк в сериализованном выводе. По умолчанию используется \n, потому что это внутренняя дисциплина конца строки, используемая Python, хотя RFC требует \r\n.

cte_type

Управляет типом кодировок передачи содержимого, которые могут использоваться или должны использоваться. Возможные значения:

7bit все данные должны быть «7-разрядными чистыми» (только ASCII). Это означает, что при необходимости данные будут закодированы с использованием либо заковыченной-печати, либо кодировки base64.
8bit данные не ограничены только 7-разрядами. Данные в заголовках по-прежнему должны быть только ASCII и поэтому будут кодированный (см. fold_binary() и utf8 ниже для исключений), но части body могут использовать 8bit CTE.

Значение cte_type 8bit работает только с BytesGenerator, но не с Generator, поскольку строки не могут содержать двоичные данные. Если Generator работает в соответствии с политикой, в которой указан cte_type=8bit, он будет действовать так, как если бы cte_type был 7bit.

raise_on_defect

Если True, любые обнаруженные дефекты будут считаться ошибками. Если False (по умолчанию), дефекты будут переданы в метод register_defect().

mangle_from_

Если True, строки, начинающиеся с «From « в теле, экранируются, помещая перед ними >. Данный параметр используется, когда сообщение сериализуется генератором. По умолчанию: False.

Добавлено в версии 3.5: Параметр mangle_from_.

message_factory

Функция фабрика для создания нового пустого объекта сообщения. Используется синтаксическим анализатором при построении сообщений. По умолчанию используется None, в этом случае используется Message.

Добавлено в версии 3.6.

Следующий метод Policy предназначен для вызова кодом с использованием библиотеки email для создания экземпляров политики с настраиваемыми параметрами:

clone(**kw)

Возвращает новый экземпляр Policy, атрибуты которого имеют те же значения, что и текущий экземпляр, за исключением случаев, когда этим атрибутам присваиваются новые значения ключевыми аргументами.

Остальные методы Policy вызываются кодом пакета email и не предназначены для вызова приложением, использующим пакет email. Пользовательская политика должна реализовывать все данные методы.

handle_defect(obj, defect)

Обрабатывает defect, найденный на obj. Когда пакет email вызывает данный метод, defect всегда будет подклассом Defect.

Реализация по умолчанию проверяет флаг raise_on_defect. Если это True, в качестве исключения вызывается defect. Если это False (по умолчанию), obj и defect передаются в register_defect().

register_defect(obj, defect)

Регистрация defect на obj. В пакете email defect всегда будет подклассом Defect.

Реализация по умолчанию вызывает метод append атрибута defects obj. Когда пакет email вызывает handle_defect, у obj обычно есть атрибут defects с методом append. Пользовательские типы объектов, используемые с пакетом email (например, настраиваемые объекты Message), также должны предоставлять такой атрибут, иначе дефекты в проанализированных сообщениях вызовут непредвиденные ошибки.

header_max_count(name)

Возвращает максимально допустимое количество заголовков с именем name.

Вызывается при добавлении заголовка к объекту EmailMessage или Message. Если возвращаемое значение не является 0 или None, и уже есть несколько заголовков с именем name, большим или равным возвращаемому значению, вызывается ValueError.

Поскольку поведение Message.__setitem__ по умолчанию заключается в добавлении значения к списку заголовков, можно легко создает повторяющиеся заголовки, не осознавая этого. Данный метод позволяет ограничить количество экземпляров некоторых заголовков, которые могут быть добавлены в Message программно. (Ограничение не соблюдается синтаксическим анализатором, который будет точно создавать столько заголовков, сколько существует в анализируемом сообщении.)

Реализация по умолчанию возвращает None для всех имён заголовков.

header_source_parse(sourcelines)

Пакет email вызывает данный метод со списком строк, каждая строка заканчивается символами разделителями строк, найденными в анализируемом источнике. Первая строка включает имя заголовка поля и разделитель. Все пробелы в исходниках сохраняются. Метод должен возвращать кортеж (name, value), который должен храниться в Message для представления распарсенного заголовка.

Если реализация хочет сохранить совместимость с существующими политиками пакетов email, name должно быть именем с сохранением регистра (все символы до разделителя «:»), а value должно быть развернутым значением (все символы-разделители строк удалены, но пробелы сохранены) очищенным от начальных пробелов.

sourcelines может содержать двоичные данные с суррогатным кодированием.

Реализации по умолчанию нет.

header_store_parse(name, value)

Пакет email вызывает данный метод с именем и значением, предоставленным прикладной программой, когда прикладная программа программно изменяет Message (в отличие от Message, созданного синтаксическим анализатором). Метод должен возвращать кортеж (name, value), который должен храниться в Message для представления заголовка.

Если реализация хочет сохранить совместимость с существующими политиками пакетов email, name и value должны быть строками или строковыми подклассами, которые не изменяют содержимое передаваемых аргументов.

Реализации по умолчанию нет.

header_fetch_parse(name, value)

Пакет email вызывает данный метод с name и value, которые в настоящее время хранятся в Message, когда данный заголовок запрашивается прикладной программой, и все, что возвращает метод, передаётся обратно в приложение в качестве значения извлекаемого заголовка. Обратите внимание, что в Message может храниться более одного заголовка с одним и тем же именем; методу передаётся конкретное имя и значение заголовка, предназначенного для возврата в приложение.

value может содержать суррогатные экранированные двоичные данные. В значении, возвращаемом методом, не должно быть суррогатных бинарных данных с экранированием.

Реализации по умолчанию нет.

fold(name, value)

Пакет email вызывает данный метод с name и value, которые в настоящее время хранятся в Message для данного заголовка. Метод должен возвращать строку, которая представляет данный заголовок «свернутым» правильно (в соответствии с параметрами политики), составив name с value и вставив символы linesep в соответствующие места. См. RFC 5322 для обсуждения правил складывания (folding) заголовков электронной почты.

value может содержать суррогатные экранированные двоичные данные. В строке, возвращаемой методом, не должно быть суррогатных бинарных данных с экранированием.

fold_binary(name, value)

То же, что и fold(), за исключением того, что возвращаемое значение должно быть байтовым объектом, а не строкой.

value может содержать суррогатные экранированные двоичные данные. Их можно преобразовывает обратно в двоичные данные в возвращаемом объекте байтов.

class email.policy.EmailPolicy(**kw)

Данный Policy реализует поведение, которое должно полностью соответствовать текущим RFC электронной почты. К ним относятся (но не ограничиваются ими) RFC 5322, RFC 2047 и текущие RFC MIME.

Политика добавляет новые алгоритмы парсинга и свертывания заголовков. Вместо простых строк заголовки представляют собой подклассы str с атрибутами, зависящими от типа поля. Алгоритм разбора и сворачивания полностью реализует RFC 2047 и RFC 5322.

Значение по умолчанию для атрибута message_factoryEmailMessage.

В дополнение к перечисленным выше настраиваемым атрибутам, которые применяются ко всем политикам, эта политика добавляет следующие дополнительные атрибуты:

Добавлено в версии 3.6: [1]

utf8

Если False, используется RFC 5322, поддерживая символы, отличные от ASCII, в заголовках, кодируя их как «закодированные слова». Если True, следовать RFC 6532 и использовать кодировку utf-8 для заголовков. Сообщения, отформатированные таким образом, могут передаваться на SMTP-серверы, поддерживающие расширение SMTPUTF8 (RFC 6531).

refold_source

Если значение заголовка в объекте Message получено из parser (а не задано программой), данный атрибут указывает, должен ли генератор повторно сворачивать это значение при преобразовании сообщения обратно в сериализованную форму. Возможные значения:

none все исходные значения используют оригинальное свертывание
long исходные значения, которые имеют любую строку длиннее max_line_length будут свернуты
all все значения свернуты.

По умолчанию long.

header_factory

Вызываемый объект, принимающий два аргумента, name и value, где name — это имя поля заголовка, а value — развернутое значение поля заголовка, и возвращает строковый подкласс, представляющий данный заголовок. По умолчанию предоставляется header_factory (см. headerregistry), который поддерживает пользовательский анализ для различных типов полей заголовка RFC 5322 с адресом и датой, а также основных типов полей заголовка MIME. Поддержка дополнительного пользовательского парсинга будет добавлена в будущем.

content_manager

Объект как минимум с двумя методами: get_content и set_content. Когда вызывается метод get_content() или set_content() объекта EmailMessage, он вызывает соответствующий метод этого объекта, передавая ему объект сообщения в качестве первого аргумента и любые аргументы или ключевые слова, которые были переданы ему в качестве дополнительных аргументов. По умолчанию для content_manager установлено значение raw_data_manager.

Добавлено в версии 3.4.

Класс предоставляет следующие реализации абстрактных методов Policy:

header_max_count(name)

Возвращает значение атрибута max_count специализированного класса, используемого для представления заголовка с заданным именем.

header_source_parse(sourcelines)

Имя анализируется как все до «:» и возвращается без изменений. Значение определяется удалением начальных пробелов из оставшейся части первой строки, объединением всех последующих строк вместе и удалением всех завершающих символов возврата каретки или перевода строки.

header_store_parse(name, value)

Имя возвращается без изменений. Если входное значение имеет атрибут name и соответствует name без учета регистра, значение возвращается без изменений. В противном случае name и value передаются в header_factory, а результирующий объект заголовка возвращается в качестве значения. В этом случае вызывается ValueError, если входное значение содержит символы CR или LF.

header_fetch_parse(name, value)

Если значение имеет атрибут name, оно возвращается в неизмененном виде. В противном случае name и value с удаленными символами CR или LF передаются в header_factory, и возвращается результирующий объект заголовка. Любые суррогатные экранированные байты превращаются в глиф неизвестного символа Юникода.

fold(name, value)

Сворачивание заголовков управляется параметром политики refold_source. Значение считается «исходным значением» тогда и только тогда, когда у него нет атрибута name (наличие атрибута name означает, что это какой-то объект заголовка). Если исходное значение необходимо преобразовывает в соответствии с политикой, оно преобразуется в объект заголовка путём передачи name и value с удаленными символами CR и LF в header_factory. Свертывание объекта заголовка выполняется путём вызова его метода fold с текущей политикой.

Исходные значения разбиты на строки с использованием splitlines(). Если значение не должно быть преобразовано, строки соединяются с использованием linesep из политики и возвращаются. Исключением являются строки, содержащие не-ASCII двоичные данные. В этом случае значение преобразуется независимо от настройки refold_source, что приводит к тому, что двоичные данные кодируются CTE с использованием набора символов unknown-8bit.

fold_binary(name, value)

То же, что и fold(), если cte_type равно 7bit, за исключением того, что возвращаемое значение — байты.

Если cte_type равен 8bit, отличные от ASCII двоичные данные, преобразуются обратно в байты. Заголовки с двоичными данными не сворачиваются, независимо от параметра refold_header, поскольку невозможно узнать, состоят ли двоичные данные из однобайтовых или многобайтовых символов.

Следующие экземпляры EmailPolicy предоставляют значения по умолчанию, подходящие для конкретных доменов приложений. Обратите внимание, что в будущем поведение данных экземпляров (в частности, экземпляра HTTP) может быть скорректировано, чтобы ещё больше соответствовать RFC, относящимся к их доменам.

email.policy.default

Экземпляр EmailPolicy со всеми неизменными значениями по умолчанию. Эта политика использует стандартные окончания строк Python \n, а не RFC- корректные \r\n.

email.policy.SMTP

Подходит для сериализации сообщений в соответствии с RFC электронной почты. Аналогично default, но с linesep, установленным на \r\n, что соответствует RFC.

email.policy.SMTPUTF8

То же, что и SMTP, за исключением того, что utf8 — это True. Полезно для сериализации сообщений в хранилище сообщений без использования закодированных слов в заголовках. Следует использовать только для передачи SMTP, если адреса отправителя или получателя содержат символы, отличные от ASCII (метод smtplib.SMTP.send_message() обрабатывает это автоматически).

email.policy.HTTP

Подходит для сериализации заголовков для использования в HTTP-трафике. Аналогичен SMTP, за исключением того, что max_line_length имеет значение None (неограниченно).

email.policy.strict

Удобный экземпляр. То же, что и default, за исключением того, что raise_on_defect имеет значение True. Это позволяет сделать любую политику строгой в письменной форме:

somepolicy + policy.strict

Со всеми EmailPolicies эффективный API пакета email отличается от API Python 3.2 следующими особенностями:

  • Установка заголовка для Message приводит к анализу этого заголовка и созданию объекта заголовка.
  • Извлечение значения заголовка из Message приводит к анализу этого заголовка, созданию и возврату объекта заголовка.
  • Любой объект заголовка или любой заголовок, свернутый в соответствии с параметрами политики, складывается с использованием алгоритма, который полностью реализует алгоритмы свертывания RFC, включая знание того, где требуются и разрешены закодированные слова.

С точки зрения приложения это означает, что любой заголовок, полученный с помощью EmailMessage, является объектом заголовка с дополнительными атрибутами, строковое значение которого представляет собой полностью декодированное Юникод значение заголовка. Точно так же заголовку может быть присвоено новое значение или создан новый заголовок с использованием Юникод строки, и политика позаботится о преобразовании Юникод строки в правильную форму, закодированную RFC.

Объекты заголовков и их атрибуты рассмотрены в headerregistry.

class email.policy.Compat32(**kw)

Данный Policy является политикой обратной совместимости. Он повторяет поведение пакета email в Python 3.2. Модуль policy также определяет экземпляр этого класса, compat32, используемый в качестве политики по умолчанию. Таким образом, поведение пакета email по умолчанию заключается в обеспечении совместимости с Python 3.2.

Следующие атрибуты имеют значения, отличные от значения по умолчанию Policy:

mangle_from_

По умолчанию True.

Класс предоставляет следующие реализации абстрактных методов Policy:

header_source_parse(sourcelines)

Имя анализируется как все до «:» и возвращается без изменений. Значение определяется удалением начальных пробелов из оставшейся части первой строки, объединением всех последующих строк вместе и удалением всех завершающих символов возврата каретки или перевода строки.

header_store_parse(name, value)

Имя и значение возвращаются без изменений.

header_fetch_parse(name, value)

Если значение содержит двоичные данные, оно преобразуется в объект Header с использованием набора символов unknown-8bit. В противном случае он возвращается без изменений.

fold(name, value)

Заголовки складываются (folded) с использованием алгоритма свертки Header, который сохраняет существующие разрывы строк в значении и переносит каждую полученную строку в max_line_length. Двоичные данные, отличные от ASCII, кодируются CTE с использованием набора символов unknown-8bit.

fold_binary(name, value)

Заголовки складываются (folded) с использованием алгоритма свертки Header, сохраняющий существующие разрывы строк в значении и переносит каждую полученную строку в max_line_length. Если cte_type равен 7bit, двоичные данные, отличные от ascii, кодируются CTE с использованием набора символов unknown-8bit. В противном случае используется исходный заголовок с существующими разрывами строк и любыми (недопустимыми RFC) двоичными данными, которые он может содержать.

email.policy.compat32

Экземпляр Compat32, обеспечивающий обратную совместимость с поведением пакета email в Python 3.2.

Сноски

[1]Первоначально добавлен в 3.3 как временная особенность.