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, должно быть удалено и обработано, а оставшееся содержимоеkw(иargs) передано методу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.
-
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представляет отдельный адрес, не входящий в группу.
-