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

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


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

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

При использовании любого из объектов политики, производных от EmailPolicy, все заголовки создаются с помощью HeaderRegistry и имеют BaseHeader в качестве последнего базового класса. У каждого класса заголовков есть дополнительный базовый класс, который определяется типом заголовка. Например, у многих заголовков класс UnstructuredHeader является другим базовым классом. Специализированный второй класс для заголовка определяется по имени заголовка с использованием таблицы поиска, хранящейся в HeaderRegistry. Все это управляется прозрачно для обычной прикладной программы, но предусмотрены интерфейсы для изменения поведения по умолчанию для использования более сложными приложениями.

В приведенных ниже разделах сначала описываются базовые классы заголовков и их атрибуты, затем API для изменения поведения HeaderRegistry и, наконец, вспомогательные классы, используемые для представления данных, проанализированных из структурированных заголовков.

class email.headerregistry.BaseHeader(name, value)

имя и значение передаются в BaseHeader из вызова header_factory. Строковым значением любого объекта header является значение, полностью декодированное в unicode.

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

name

Имя заголовка (часть поля перед „:“). Это именно то значение, которое было передано при вызове header_factory для name; то есть регистр сохранен.

defects

Набор HeaderDefect экземпляров, сообщающих о любых проблемах с соблюдением требований RFC, обнаруженных во время синтаксического анализа. Пакет электронной почты пытается предоставить полную информацию об обнаружении проблем с соблюдением требований. Смотрите модуль errors для обсуждения типов дефектов, о которых может быть сообщено.

max_count

Максимальное количество заголовков этого типа, которые могут иметь одинаковое значение name. Значение None означает неограниченное. Значением BaseHeader для этого атрибута является None; ожидается, что специализированные классы заголовков будут переопределять это значение по мере необходимости.

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

fold(*, policy)

Возвращает строку, содержащую linesep символов, необходимых для правильного сворачивания заголовка в соответствии с политикой. cte_type из 8bit будет обрабатываться так, как если бы это было 7bit, поскольку заголовки могут не содержать произвольных двоичных данных. Если utf8 равно False, данные, отличные от ASCII, будут закодированы в RFC 2047.

BaseHeader сам по себе не может использоваться для создания объекта header. Он определяет протокол, с которым взаимодействует каждый специализированный заголовок для создания объекта header. В частности, 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, должно быть удалено и обработано, а оставшееся содержимое kwargs) должно быть передано в BaseHeader init способ.

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 значением * может быть 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__ сгенерированного класса.

По умолчанию используются следующие сопоставления:

предмет:

Уникальный структурированный заголовок

дата:

Уникальный заголовок данных

дата повторной отправки:

Заголовок даты

первоначальная дата:

Уникальный заголовок данных

отправитель:

Уникальный заголовок Singleaddresssheader

отправитель жалобы:

Заголовок с одним адресом

к:

Уникальный адресный заголовок

негодовать-на:

Адресный справочник

куб.см:

Уникальный адресный заголовок

возмущаться-cc:

Адресный справочник

оцк:

Уникальный адресный заголовок

возмущаться-bcc:

Адресный справочник

от:

Уникальный адресный заголовок

возмущаться-от:

Адресный справочник

ответить-кому:

Уникальный адресный заголовок

мим-версия:

Заголовок Mimeversion

тип содержимого:

ContentTypeHeader - заголовок типа содержимого

содержание-расположение:

ContentDispositionHeader - Заголовок размещения содержимого

передача контента-кодирование:

Заголовок ContentTransferEncodingHeader

идентификатор сообщения:

Заголовок сообщения

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

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 и предоставления списка единый адрес в виде адресов.

display_name

display_name из группы. Если это None и в addresses есть ровно один Address, то Group представляет собой отдельный адрес, который не входит в группу.

addresses

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

__str__()

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

Сноски

Вернуться на верх