Документация Python неофициальный перевод

19.1.5. email.headerregistry: Пользовательские объекты заголовковemail.headerregistry: Custom Header Objects

Новое в версии 3.3: в качестве временного модуля.

Исходный код: Lib/email/headerregistry.py

Примечание

Модуль headerregistry был включён в стандартную библиотеку на временной основе. Обратно несовместимые изменения (вплоть до удаления модуля) могут произойти, если основные разработчики сочтут это необходимым.


Заголовки представлены настраиваемыми подклассами str. Конкретный класс, используемый для представления данного заголовка, определяется header_factory policy, действующей на момент создания заголовков. В этом разделе описаны конкретные header_factory, реализованные в пакете email для обработки RFC 5322-совместимых сообщений электронной почты. Они не только предоставляют настраиваемые объекты заголовков для различных типов заголовков, но и содержат механизм расширения, позволяющий приложениям добавлять собственные типы заголовков.

При использовании любого объекта политики, производного от 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 символов, необходимых для правильного складывания заголовка в соответствии с политикой. cte_type из 8bit будет обрабатываться, как если бы это был 7bit, так как строки не могут содержать двоичные данные.

Сам по себе BaseHeader не может использоваться для создания объекта заголовка. Он определяет протокол, с которым взаимодействует каждый специализированный заголовок для создания объекта заголовка. В частности, BaseHeader требует, чтобы специализированный класс предоставлял classmethod() с именем parse. Этот метод вызывается следующим образом:

parse(string, kwds)

kwds – это словарь, содержащий один предварительно инициализированный ключ, defects. defects – это пустой список. Метод parse должен добавлять любые обнаруженные дефекты в этот список. После возврата словарь kwds должен содержать значения как минимум для ключей decoded и defects. decoded должен быть строковым значением заголовка (то есть значение заголовка, полностью декодированное в Unicode). Метод parse должен предполагать, что строка может содержать части, закодированные для транспорта, но также должен правильно обрабатывать все допустимые символы Unicode, чтобы можно было разбирать незакодированные значения заголовков.

Затем __new__ из BaseHeader создаёт экземпляр заголовка и вызывает его метод init. Специализированному классу нужно предоставить метод init только в том случае, если он хочет установить дополнительные атрибуты, выходящие за рамки тех, что предоставляет сам BaseHeader. Такой метод init должен выглядеть следующим образом:

def init(self, *args, **kw):
    self._myattr = kw.pop('myattr')
    super().init(*args, **kw)

То есть всё лишнее, что специализированный класс поместил в словарь kwds, должно быть удалено и обработано, а оставшееся содержимое kwargs) передано методу init из BaseHeader.

class email.headerregistry.UnstructuredHeader

«Неструктурированный» заголовок – это тип заголовка по умолчанию в RFC 5322. Любой заголовок, не имеющий заданного синтаксиса, считается неструктурированным. Классический пример неструктурированного заголовка – Subject.

В RFC 5322 неструктурированный заголовок представляет собой последовательность произвольного текста в наборе символов ASCII. Однако RFC 2047 имеет совместимый с RFC 5322 механизм для кодирования не-ASCII текста как символов ASCII внутри значения заголовка. Когда значение, содержащее закодированные слова, передаётся конструктору, анализатор 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, кодирующих все отдельные адреса из значения заголовка. Если значение заголовка содержит группы, отдельные адреса из группы включаются в список в том месте, где группа встречается в значении (то есть список адресов «уплощается» до одномерного списка).

Значение decoded заголовка будет иметь все закодированные слова, декодированные в Unicode. Закодированные доменные имена idna также декодируются в Unicode. Значение decoded устанавливается joining значения 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.

cte

Допустимые значения: 7bit, 8bit, base64 и quoted-printable. Подробнее см. RFC 2045.

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 не разрешён в части имени пользователя адреса.

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 представляет отдельный адрес, не входящий в группу.

addresses

Возможно пустой кортеж объектов Address, представляющих адреса в группе.

__str__()

Значение str объекта Group форматируется в соответствии с RFC 5322, но без кодирования передачи содержимого для любых не-ASCII символов. Если display_name равно None и в списке addresses есть один Address, то значение str будет совпадать со значением str этого единственного Address.