email.headerregistry: Custom Header Objects

Вихідний код: Lib/email/headerregistry.py


Added in version 3.6: [1]

Заголовки представлені налаштованими підкласами str. Конкретний клас, який використовується для представлення даного заголовка, визначається header_factory policy, що діє під час створення заголовків. У цьому розділі описано конкретну header_factory, реалізовану пакетом електронної пошти для обробки 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, виявлені під час аналізу. Пакет електронної пошти намагається бути повним щодо виявлення проблем відповідності. Перегляньте модуль errors для обговорення типів дефектів, про які можна повідомити.

max_count

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

BaseHeader також надає наступний метод, який викликається кодом бібліотеки електронної пошти і, як правило, не повинен викликатися прикладними програмами:

fold(*, policy)

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

BaseHeader сам по собі не може використовуватися для створення об’єкта заголовка. Він визначає протокол, з яким співпрацює кожен спеціалізований заголовок, щоб створити об’єкт заголовка. Зокрема, BaseHeader вимагає, щоб спеціалізований клас надавав classmethod() під назвою parse. Цей метод називається наступним чином:

parse(string, kwds)

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

Потім __new__ BaseHeader створює екземпляр заголовка та викликає його метод 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 у значенні заголовка. Коли значення, що містить закодовані слова, передається конструктору, аналізатор UnstructuredHeader перетворює такі закодовані слова в юнікод, дотримуючись правил RFC 2047 для неструктурованого тексту. Синтаксичний аналізатор використовує евристику, щоб спробувати декодувати певні невідповідні закодовані слова. У таких випадках реєструються дефекти, а також такі дефекти, як недійсні символи в закодованих словах або незакодований текст.

Цей тип заголовка не містить додаткових атрибутів.

class email.headerregistry.DateHeader

RFC 5322 визначає дуже специфічний формат для дат у заголовках електронних листів. Синтаксичний аналізатор DateHeader розпізнає цей формат дати, а також розпізнає низку варіантних форм, які іноді зустрічаються «в дикій природі».

Цей тип заголовка надає такі додаткові атрибути:

datetime

If the header value can be recognized as a valid date of one form or another, this attribute will contain a datetime instance representing that date. If the timezone of the input date is specified as -0000 (indicating it is in UTC but contains no information about the source timezone), then datetime will be a naive datetime. If a specific timezone offset is found (including +0000), then datetime will contain an aware datetime that uses datetime.timezone to record the timezone offset.

Значення 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, що кодує адреси та групи, знайдені у значенні заголовка. Адреси, які не є частиною групи, представлені в цьому списку як одноадресні Групи, у яких display_name має значення None.

addresses

Кортеж об’єктів Address, що кодує всі окремі адреси зі значення заголовка. Якщо значення заголовка містить будь-які групи, окремі адреси з групи включаються до списку в тому місці, де група зустрічається у значенні (тобто список адрес «зрівнюється» в одновимірний список).

The decoded value of the header will have all encoded words decoded to unicode. idna encoded domain names are also decoded to unicode. The decoded value is set by joining the str value of the elements of the groups attribute with ', '.

Для встановлення значення заголовка адреси можна використовувати список об’єктів Address і 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)

This is the factory used by EmailPolicy by default. HeaderRegistry builds the class used to create a header instance dynamically, using base_class and a specialized class retrieved from a registry that it holds. When a given header name does not appear in the registry, the class specified by default_class is used as the specialized class. When use_default_map is True (the default), the standard mapping of header names to classes is copied in to the registry during initialization. base_class is always the last class in the generated class’s __bases__ list.

Відображення за замовчуванням:

тема:

UniqueUnstructuredHeader

дата:

UniqueDateHeader

дата повторного відправлення:

DateHeader

дата виходу:

UniqueDateHeader

відправник:

UniqueSingleAddressHeader

resent-sender:

SingleAddressHeader

до:

UniqueAddressHeader

обурюватися:

AddressHeader

cc:

UniqueAddressHeader

resent-cc:

AddressHeader

прихована копія:

UniqueAddressHeader

resent-bcc:

AddressHeader

від:

UniqueAddressHeader

обурюватися-від:

AddressHeader

відповідати на:

UniqueAddressHeader

мім-версія:

MIMEVersionHeader

тип вмісту:

ContentTypeHeader

зміст-диспозиція:

ContentDispositionHeader

кодування передачі вмісту:

ContentTransferEncodingHeader

ідентифікатор повідомлення:

MessageIDHeader

HeaderRegistry має такі методи:

map_to_type(self, name, cls)

ім’я — це ім’я заголовка, який буде зіставлено. У реєстрі його буде перетворено на нижній регістр. 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, викличе помилку. Дозволяються символи Юнікоду, які будуть закодовані властивостями під час серіалізації. Однак, згідно з RFC, Юнікод не дозволений у частині імені користувача адреси.

display_name

Частина відображуваної назви адреси, якщо така є, без лапок. Якщо адреса не має відображуваного імені, цей атрибут буде порожнім рядком.

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];

Для зручності обробки списків адрес, які складаються з суміші груп і окремих адрес, Група також може використовуватися для представлення окремих адрес, які не є частиною групи, встановивши display_name на None і надання списку однієї адреси як адрес.

display_name

display_name групи. Якщо значення None і в адресах є точно одна Адреса, тоді Група представляє одну адресу, яка не входить до групи.

addresses

Можливо, порожній кортеж об’єктів Address, що представляє адреси в групі.

__str__()

Значення str Group відформатовано відповідно до RFC 5322, але без кодування передачі вмісту будь-яких символів, відмінних від ASCII. Якщо display_name не має значення, а в списку addresses є одна Address, значення str буде таким самим, як str цього одного Address.

Виноски