19.1.5. email.headerregistry: Пользовательские объекты заголовков¶email.headerregistry: Custom Header Objects
Примечание
Модуль headerregistry был включён в стандартную библиотеку на временной основе. Обратно несовместимые изменения (вплоть до удаления модуля) могут произойти, если основные разработчики сочтут это необходимым.
Новое в версии 3.3: в качестве временного модуля.
Headers are represented by customized subclasses of str. The particular class used to represent a given header is determined by the header_factory of the policy in effect when the headers are created. This section documents the particular header_factory implemented by the email package for handling RFC 5322 compliant email messages, which not only provides customized header objects for various header types, but also provides an extension mechanism for applications to add their own custom header types.
При использовании любого из объектов политики, производных от EmailPolicy, все заголовки создаются через HeaderRegistry и имеют BaseHeader в качестве своего последнего базового класса. Каждый класс заголовка имеет дополнительный базовый класс, который определяется типом заголовка. Например, многие заголовки имеют класс UnstructuredHeader в качестве второго базового класса. Специализированный второй класс для заголовка определяется его именем с помощью таблицы поиска, хранящейся в HeaderRegistry. Все это прозрачно для типичного приложения, однако предоставляются интерфейсы для изменения поведения по умолчанию для использования более сложными приложениями.
В приведенных ниже разделах сначала документируются базовые классы заголовков и их атрибуты, затем описывается API для изменения поведения HeaderRegistry, и, наконец, вспомогательные классы, используемые для представления данных, извлеченных из структурированных заголовков.
- class email.headerregistry.BaseHeader(name, value)¶
name и value передаются в BaseHeader из вызова header_factory. Строковое значение любого объекта заголовка – это value, полностью декодированное в Unicode.
Этот базовый класс определяет следующие свойства, доступные только для чтения:
- name¶
Имя заголовка (часть поля до двоеточия). Это в точности то значение, которое передается в вызове header_factory для name; при этом регистр сохраняется.
- defects¶
Кортеж экземпляров HeaderDefect, сообщающих о любых проблемах соответствия RFC, обнаруженных при разборе. Пакет email старается максимально полно выявлять проблемы с соответствием. См. модуль errors для обсуждения типов дефектов, которые могут быть зарегистрированы.
- max_count¶
Максимальное количество заголовков данного типа, которые могут иметь одинаковое name. Значение None означает неограниченное количество. Значением этого атрибута в BaseHeader является None; ожидается, что специализированные классы заголовков при необходимости переопределят это значение.
BaseHeader также предоставляет следующий метод, который вызывается кодом библиотеки email и в общем случае не должен вызываться прикладными программами:
- fold(*, policy)¶
Возвращает строку, содержащую символы linesep, необходимые для корректного сворачивания заголовка в соответствии с policy. Значение cte_type равное 8bit будет обрабатываться так, как если бы оно было 7bit, поскольку строки не могут содержать двоичные данные.
BaseHeader сам по себе не может быть использован для создания объекта заголовка. Он определяет протокол, с которым взаимодействует каждый специализированный заголовок для создания объекта заголовка. В частности, BaseHeader требует, чтобы специализированный класс предоставлял classmethod() с именем parse. Этот метод вызывается следующим образом:
parse(string, kwds)
kwds – это словарь, содержащий один предварительно инициализированный ключ: defects. defects – пустой список. Метод parse должен добавлять в этот список любые обнаруженные дефекты. После возвращения словарь kwds должен содержать значения по крайней мере для ключей decoded и defects. decoded должно быть строковым значением заголовка (то есть значением заголовка, полностью декодированным в Unicode). Метод parse должен предполагать, что string может содержать части, закодированные для передачи, но также должен корректно обрабатывать все допустимые символы Unicode, чтобы иметь возможность разбирать незакодированные значения заголовков.
BaseHeader‘s __new__ затем создает экземпляр заголовка и вызывает его метод init. Специализированному классу нужно предоставить метод init только в том случае, если он хочет установить дополнительные атрибуты помимо тех, что предоставляет сам BaseHeader. Такой метод init должен выглядеть следующим образом:
def init(self, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
То есть любые дополнительные данные, которые специализированный класс помещает в словарь kwds, должны быть извлечены и обработаны, а оставшееся содержимое kw (и args) передано методу BaseHeader init.
- class email.headerregistry.UnstructuredHeader¶
«Неструктурированный» заголовок – это тип заголовка по умолчанию в RFC 5322. Любой заголовок, не имеющий заданного синтаксиса, считается неструктурированным. Классический пример неструктурированного заголовка – Subject.
В RFC 5322 неструктурированный заголовок представляет собой последовательность произвольных текстовых символов из набора ASCII. Однако RFC 2047 предоставляет совместимый с RFC 5322 механизм кодирования не-ASCII текста в виде ASCII символов внутри значения заголовка. Когда value, содержащее закодированные слова, передается конструктору, анализатор UnstructuredHeader преобразует такие закодированные слова обратно в исходный Unicode в соответствии с правилами RFC 2047 для неструктурированного текста. Анализатор использует эвристики для попытки декодирования некоторых некорректных закодированных слов. В таких случаях регистрируются дефекты, а также дефекты для таких проблем, как недопустимые символы внутри закодированных слов или незакодированного текста.
Этот тип заголовка не предоставляет дополнительных атрибутов.
- class email.headerregistry.DateHeader¶
RFC 5322 определяет очень конкретный формат для дат в заголовках электронной почты. Анализатор DateHeader распознает этот формат даты, а также ряд вариантов, которые иногда встречаются «в дикой природе».
Этот тип заголовка предоставляет следующие дополнительные атрибуты:
- datetime¶
Если значение заголовка может быть распознано как допустимая дата в той или иной форме, этот атрибут будет содержать экземпляр datetime, представляющий эту дату. Если часовой пояс входной даты указан как -0000 (что означает, что дата указана в UTC, но не содержит информации об исходном часовом поясе), то datetime будет наивным datetime. Если найден конкретный сдвиг часового пояса (включая +0000), то datetime будет содержать осведомленный datetime, который использует datetime.timezone для записи сдвига часового пояса.
Значение decoded заголовка определяется путем форматирования datetime в соответствии с правилами RFC 5322; то есть оно устанавливается в:
email.utils.format_datetime(self.datetime)
При создании DateHeader value может быть экземпляром datetime. Это означает, например, что следующий код корректен и делает то, что ожидается:
msg['Date'] = datetime(2011, 7, 15, 21)
Поскольку это наивный datetime, он будет интерпретирован как временная метка UTC, и результирующее значение будет иметь часовой пояс -0000. Гораздо полезнее использовать функцию localtime() из модуля utils:
msg['Date'] = utils.localtime()
В этом примере заголовок даты устанавливается в текущее время и дату с использованием текущего сдвига часового пояса.
- class email.headerregistry.AddressHeader¶
Заголовки адресов – одни из самых сложных типов структурированных заголовков. Класс AddressHeader предоставляет универсальный интерфейс для любого заголовка адреса.
Этот тип заголовка предоставляет следующие дополнительные атрибуты:
- groups¶
Кортеж объектов Group, кодирующих адреса и группы, найденные в значении заголовка. Адреса, не входящие в группу, представлены в этом списке как Groups с одним адресом, у которых display_name равен None.
- addresses¶
Кортеж объектов Address, кодирующих все отдельные адреса из значения заголовка. Если значение заголовка содержит какие-либо группы, отдельные адреса из группы включаются в список в том месте, где эта группа встречается в значении (то есть список адресов сводится к одномерному списку).
Декодированное значение заголовка будет содержать все закодированные слова, декодированные в Юникод. idna-закодированные доменные имена также декодируются в Юникод. Декодированное значение устанавливается объединением (join) строковых представлений (str) элементов атрибута groups с ', '.
Список объектов Address и Group в любом сочетании может использоваться для установки значения заголовка адреса. Объекты Group, у которых display_name равен None, будут интерпретироваться как отдельные адреса, что позволяет копировать список адресов с сохранением групп, используя список, полученный из атрибута groups исходного заголовка.
- class email.headerregistry.SingleAddressHeader¶
Подкласс AddressHeader, добавляющий один дополнительный атрибут:
- address¶
Единственный адрес, закодированный значением заголовка. Если значение заголовка фактически содержит более одного адреса (что является нарушением RFC при использовании политики по умолчанию policy), обращение к этому атрибуту приведёт к ValueError.
Многие из перечисленных классов также имеют вариант Unique (например, UniqueUnstructuredHeader). Единственное отличие состоит в том, что в варианте Unique параметр max_count установлен в 1.
- class email.headerregistry.MIMEVersionHeader¶
На самом деле для заголовка MIME-Version существует только одно допустимое значение – 1.0. Для обеспечения совместимости в будущем этот класс заголовков поддерживает и другие допустимые номера версий. Если номер версии соответствует допустимому значению согласно RFC 2045, то объект заголовка будет иметь не None значения следующих атрибутов:
- version¶
Номер версии в виде строки, из которой удалены все пробелы и/или комментарии.
- major¶
Номер основной версии в виде целого числа.
- minor¶
Номер дополнительной версии в виде целого числа.
- class email.headerregistry.ParameterizedMIMEHeader¶
Все MIME-заголовки начинаются с префикса «Content-». Каждый конкретный заголовок имеет определённое значение, описанное в соответствующем классе. Некоторые могут также принимать список дополнительных параметров, имеющих общий формат. Этот класс служит базовым для всех MIME-заголовков, принимающих параметры.
- params¶
Словарь, сопоставляющий имена параметров со значениями параметров.
- class email.headerregistry.ContentTypeHeader¶
Класс ParameterizedMIMEHeader, обрабатывающий заголовок Content-Type.
- content_type¶
Строка типа содержимого в формате maintype/subtype.
- maintype¶
- subtype¶
- class email.headerregistry.ContentDispositionHeader¶
Класс ParameterizedMIMEHeader, обрабатывающий заголовок Content-Disposition.
- content-disposition
inline и attachment – единственные допустимые значения, используемые на практике.
- class email.headerregistry.ContentTransferEncoding¶
Обрабатывает заголовок Content-Transfer-Encoding.
- class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)¶
Это фабрика, используемая по умолчанию объектом EmailPolicy. HeaderRegistry создаёт класс, используемый для динамической сборки экземпляра заголовка. В нём применяются base_class и специализированный класс, получаемый из внутреннего реестра. Если указанное имя заголовка отсутствует в реестре, в качестве специализированного класса используется класс, заданный через default_class. Когда use_default_map равно True (значение по умолчанию), во время инициализации в реестр копируется стандартное соответствие имён заголовков классам. base_class всегда является последним классом в списке __bases__ созданного класса.
Стандартные сопоставления:
subject: UniqueUnstructuredHeader date: UniqueDateHeader resent-date: DateHeader orig-date: UniqueDateHeader sender: UniqueSingleAddressHeader resent-sender: SingleAddressHeader to: UniqueAddressHeader resent-to: AddressHeader cc: UniqueAddressHeader resent-cc: AddressHeader from: UniqueAddressHeader resent-from: AddressHeader reply-to: UniqueAddressHeader HeaderRegistry имеет следующие методы:
- map_to_type(self, name, cls)¶
name – это имя сопоставляемого заголовка. Оно будет преобразовано в нижний регистр в реестре. cls – это специализированный класс, используемый, вместе с base_class, для создания класса, с помощью которого создаются экземпляры заголовков, соответствующих name.
- __getitem__(name)¶
Создаёт и возвращает класс для создания заголовка name.
- __call__(name, value)¶
Извлекает из реестра специализированный заголовок, связанный с name (используя default_class, если name отсутствует в реестре), и объединяет его с base_class для получения нового класса, вызывает конструктор созданного класса, передавая ему тот же список аргументов, и, наконец, возвращает полученный экземпляр класса.
Следующие классы используются для представления данных, извлечённых при разборе структурированных заголовков. В общем случае прикладная программа может применять их для формирования структурированных значений, присваиваемых конкретным заголовкам.
- class email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)¶
Класс, используемый для представления адреса электронной почты. Общий вид адреса:
[display_name] <username@domain>
или:
username@domain
где каждая часть должна соответствовать определённым правилам синтаксиса, изложенным в RFC 5322.
В целях удобства вместо addr_spec можно указать username и domain; в этом случае username и domain будут извлечены из addr_spec. addr_spec должна быть правильно процитированной строкой в формате RFC; если это не так, Address вызовет ошибку. Допускаются символы Unicode, которые будут соответствующим образом закодированы при сериализации. Однако согласно RFC, Unicode не допускается в части имени пользователя (username).
- display_name¶
Часть адреса, содержащая отображаемое имя, если оно есть, с удалёнными кавычками. Если у адреса нет отображаемого имени, этот атрибут будет пустой строкой.
- username¶
Часть адреса username, из которой удалены все кавычки.
- domain¶
Часть адреса domain.
- addr_spec¶
Часть адреса username@domain, правильно процитированная для использования в качестве самостоятельного адреса (вторая форма, показанная выше). Этот атрибут не является изменяемым.
- __str__()¶
Строковое значение str объекта – это адрес, процитированный в соответствии с правилами RFC 5322, но без кодирования пересылки содержимого для любых не-ASCII символов.
Для поддержки SMTP (RFC 5321) класс Address обрабатывает один особый случай: если username и domain оба являются пустыми строками (или None), то строковое значение Address равно <>.
- class email.headerregistry.Group(display_name=None, addresses=None)¶
Класс, используемый для представления группы адресов. Общий вид группы адресов:
display_name: [address-list];
Для удобства обработки списков адресов, состоящих из смеси групп и отдельных адресов, Group может также использоваться для представления отдельных адресов, не входящих в группу, путём установки display_name в None и передачи списка из одного адреса в качестве addresses.
- display_name¶
display_name группы. Если оно равно None и в addresses есть ровно один Address, то Group представляет собой отдельный адрес, не входящий в группу.
- __str__()¶
Строковое значение str объекта Group форматируется в соответствии с RFC 5322, но без кодирования пересылки содержимого для любых не-ASCII символов. Если display_name равно none и в списке addresses есть единственный Address, то строковое значение str будет таким же, как str этого единственного Address.