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

Источник: Lib/email/headerregistry.py


Added in version 3.6: [1]

Заголовки представляются настраиваемыми подклассами 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. Строковое значение любого объекта заголовка - это значение, полностью декодированное в юникод.

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

name

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

defects

Кортеж из HeaderDefect экземпляров, сообщающих о любых проблемах с соответствием RFC, обнаруженных при разборе. Пакет email старается быть полным в обнаружении проблем с соответствием. Обсуждение типов дефектов, о которых может быть сообщено, см. в модуле errors.

max_count

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

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

fold(*, policy)

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

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

parse(string, kwds)

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

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

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

тема:

UniqueUnstructuredHeader

дата:

UniqueDateHeader

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

DateHeader

дата происхождения:

UniqueDateHeader

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

UniqueSingleAddressHeader

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

SingleAddressHeader

на:

UniqueAddressHeader

resent-to:

AddressHeader

cc:

UniqueAddressHeader

resent-cc:

AddressHeader

bcc:

UniqueAddressHeader

resent-bcc:

AddressHeader

с сайта:

UniqueAddressHeader

resent-from:

AddressHeader

ответ на:

UniqueAddressHeader

mime-version:

MIMEVersionHeader

content-type:

ContentTypeHeader

content-disposition:

ContentDispositionHeader

content-transfer-encoding:

ContentTransferEncodingHeader

message-id:

MessageIDHeader

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.

Для удобства вместо username и domain можно указать addr_spec, в этом случае username и domain будут разобраны из addr_spec. addr_spec должен быть правильной строкой, заключенной в кавычки RFC; если это не так, то Address вызовет ошибку. Символы Юникода разрешены и будут закодированы в свойствах при сериализации. Однако, согласно RFC, юникод не разрешен в части имени пользователя адреса.

display_name

Часть адреса, содержащая отображаемое имя, если таковое имеется, с удалением всех кавычек. Если адрес не имеет отображаемого имени, этот атрибут будет пустой строкой.

username

Часть адреса username, в которой удалены все кавычки.

domain

Часть адреса domain.

addr_spec

Часть адреса username@domain, правильно заключенная в кавычки для использования в качестве пустого адреса (вторая форма, показанная выше). Этот атрибут не изменяется.

__str__()

Значение str объекта - это адрес, приведенный в соответствии с правилами RFC 5322, но без кодировки Content Transfer Encoding любых не-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 отсутствует и в списке addresses есть единственный Address, значение str будет таким же, как str этого единственного Address.

Сноски