# `email.parser`: Parsing email messages

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

Структури об’єктів повідомлень можна створити одним із двох способів: їх можна створити з цілої тканини, створивши об’єкт `EmailMessage`, додавши заголовки за допомогою інтерфейсу словника та додавши корисне(і) навантаження за допомогою `set_content()` і пов’язані методи, або їх можна створити шляхом аналізу серіалізованого представлення повідомлення електронної пошти.

Пакет `email` надає стандартний аналізатор, який розуміє більшість структур документів електронної пошти, включаючи документи MIME. Ви можете передати аналізатору байти, рядок або файловий об’єкт, і аналізатор поверне вам кореневий екземпляр `EmailMessage` структури об’єкта. Для простих повідомлень без MIME корисним навантаженням цього кореневого об’єкта, ймовірно, буде рядок, що містить текст повідомлення. Для повідомлень MIME кореневий об’єкт поверне `True` зі свого методу `is_multipart()`, а доступ до підчастин можна отримати за допомогою методів маніпулювання корисним навантаженням, таких як `get_body()`, `iter_parts()` і `walk()`.

Насправді існує два інтерфейси синтаксичного аналізатора, доступні для використання: `Parser` API та інкрементальний `FeedParser` API. API `Parser` найбільш корисний, якщо у вас є весь текст повідомлення в пам’яті або якщо все повідомлення зберігається у файлі у файловій системі. `FeedParser` більше підходить, коли ви читаєте повідомлення з потоку, який може блокувати очікування додаткового введення (наприклад, читання повідомлення електронної пошти з сокета). `FeedParser` може споживати та аналізувати повідомлення поступово, і повертає кореневий об’єкт лише тоді, коли ви закриваєте аналізатор.

Note that the parser can be extended in limited ways, and of course you can implement your own parser completely from scratch. All of the logic that connects the `email` package’s bundled parser and the `EmailMessage` class is embodied in the `Policy` class, so a custom parser can create message object trees any way it finds necessary by implementing custom versions of the appropriate `Policy` methods.

## API FeedParser

`BytesFeedParser`, імпортований з модуля `email.feedparser`, надає API, який сприяє поступовому розбору повідомлень електронної пошти, як це було б необхідно під час читання тексту повідомлення електронної пошти з джерела які можуть блокувати (наприклад, сокет). Звичайно, `BytesFeedParser` можна використовувати для аналізу повідомлення електронної пошти, яке повністю міститься в bytes-like object, рядку або файлі, але API `BytesParser` може бути зручнішим для такі випадки використання. Семантика та результати двох API парсера ідентичні.

API `BytesFeedParser` простий; ви створюєте екземпляр, передаєте йому купу байтів, доки більше не залишиться, а потім закриваєте аналізатор, щоб отримати кореневий об’єкт повідомлення. `BytesFeedParser` є надзвичайно точним під час аналізу повідомлень, що відповідають стандартам, і він дуже добре справляється з аналізом невідповідних повідомлень, надаючи інформацію про те, як повідомлення було визнано зламаним. Він заповнить атрибут `defects` об’єкта повідомлення списком будь-яких проблем, знайдених у повідомленні. Дивіться модуль `email.errors`, щоб переглянути список дефектів, які він може знайти.

Ось API для `BytesFeedParser`:

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

  Створіть екземпляр `BytesFeedParser`. Необов’язковий _factory — виклик без аргументів; якщо не вказано, використовуйте `message_factory` з політики. Викликати _factory щоразу, коли потрібен новий об’єкт повідомлення.

  Якщо вказано policy, використовуйте правила, які вона визначає, щоб оновити представлення повідомлення. Якщо policy не налаштовано, використовуйте політику `compat32`, яка підтримує зворотну сумісність із версією пакета електронної пошти Python 3.2 і надає `Message` як фабрику за замовчуванням. Усі інші політики передбачають `EmailMessage` як _factory за умовчанням. Щоб дізнатися більше про те, що ще контролює policy, перегляньте документацію `policy`.

  Примітка: Ключове слово політики слід завжди вказувати; У наступній версії Python значення за умовчанням зміниться на `email.policy.default`.

  Нове в версії 3.2.

  Змінено в версії 3.3: Додано ключове слово політика.

  Змінено в версії 3.6: _factory за умовчанням використовує політику `message_factory`.

  feed(data)

    Подайте аналізатору ще трохи даних. data має бути bytes-like object, що містить один або більше рядків. Рядки можуть бути частковими, і синтаксичний аналізатор правильно з’єднає такі часткові рядки. Рядки можуть мати будь-яке з трьох загальних закінчень рядків: повернення каретки, новий рядок або повернення каретки та новий рядок (вони навіть можуть бути змішаними).

  close()

    Завершіть розбір усіх попередньо поданих даних і поверніть кореневий об’єкт повідомлення. Не визначено, що відбувається, якщо `feed()` викликається після виклику цього методу.

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

  Працює як `BytesFeedParser`, за винятком того, що вхід до методу `feed()` має бути рядком. Це має обмежену корисність, оскільки єдиний спосіб зробити таке повідомлення дійсним — це містити лише текст ASCII або, якщо `utf8` має значення `True`, не мати двійкового коду вкладення.

  Змінено в версії 3.3: Додано ключове слово політика.

## API парсера

Клас `BytesParser`, імпортований з модуля `email.parser`, надає API, який можна використовувати для аналізу повідомлення, коли повний вміст повідомлення доступний у bytes-like object або файл. Модуль `email.parser` також містить `Parser` для аналізу рядків і аналізатори лише заголовків, `BytesHeaderParser` і `HeaderParser`, які можна використовувати, якщо ви цікавляться лише заголовками повідомлень. `BytesHeaderParser` і `HeaderParser` можуть бути набагато швидшими в цих ситуаціях, оскільки вони не намагаються проаналізувати тіло повідомлення, натомість встановлюючи корисне навантаження на необроблене тіло.

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

  Створіть екземпляр `BytesParser`. Аргументи _class і policy мають те саме значення й семантику, що й аргументи _factory і policy `BytesFeedParser`.

  Примітка: Ключове слово політики слід завжди вказувати; У наступній версії Python значення за умовчанням зміниться на `email.policy.default`.

  Змінено в версії 3.3: Видалено аргумент strict, який був застарілим у версії 2.4. Додано ключове слово політика.

  Змінено в версії 3.6: _class за умовчанням використовує політику `message_factory`.

  parse(fp, headersonly=False)

    Прочитати всі дані з двійкового файлоподібного об’єкта fp, проаналізувати отримані байти та повернути об’єкт повідомлення. fp має підтримувати як методи `readline()`, так і `read()`.

    Байти, що містяться у fp, мають бути відформатовані як блок RFC 5322 (або, якщо `utf8` має значення `True`, RFC 6532 ) заголовки стилю та рядки продовження заголовка, необов’язково передуючими заголовком конверта. Блок заголовка завершується або кінцем даних, або порожнім рядком. Після блоку заголовка йде тіло повідомлення (яке може містити частини в кодуванні MIME, включаючи частини з Content-Transfer-Encoding `8bit`).

    Необов’язковий параметр headersonly — це позначка, яка вказує, чи зупиняти аналіз після читання заголовків. Типовим значенням є `False`, що означає, що аналізується весь вміст файлу.

  parsebytes(bytes, headersonly=False)

    Подібний до методу `parse()`, за винятком того, що він приймає bytes-like object замість файлоподібного об’єкта. Виклик цього методу для bytes-подібного об’єкта еквівалентний обгортанню bytes в екземплярі `BytesIO` і виклику `parse()`.

    Необов’язковий headersonly такий же, як у випадку з методом `parse()`.

  Нове в версії 3.2.

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

  Точно так само, як `BytesParser`, за винятком того, що headersonly за умовчанням має значення `True`.

  Нове в версії 3.3.

class email.parser.Parser(_class=None, *, policy=policy.compat32)

  Цей клас є паралельним до `BytesParser`, але обробляє введення рядків.

  Змінено в версії 3.3: Видалено суворий аргумент. Додано ключове слово політика.

  Змінено в версії 3.6: _class за умовчанням використовує політику `message_factory`.

  parse(fp, headersonly=False)

    Прочитати всі дані з файлоподібного об’єкта текстового режиму fp, проаналізувати отриманий текст і повернути кореневий об’єкт повідомлення. fp має підтримувати як методи `readline()`, так і `read()` для файлоподібних об’єктів.

    За винятком вимог текстового режиму, цей метод працює як `BytesParser.parse()`.

  parsestr(text, headersonly=False)

    Подібний до методу `parse()`, за винятком того, що він приймає рядковий об’єкт замість файлоподібного об’єкта. Виклик цього методу для рядка еквівалентний обгортанню тексту в екземплярі `StringIO` і виклику `parse()`.

    Необов’язковий headersonly такий же, як у випадку з методом `parse()`.

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

  Точно так само, як `Parser`, за винятком того, що headersonly за замовчуванням має значення `True`.

Оскільки створення структури об’єкта повідомлення з рядка або файлового об’єкта є таким поширеним завданням, для зручності передбачено чотири функції. Вони доступні в просторі імен пакета `email` верхнього рівня.

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

  Повертає структуру об’єкта повідомлення з bytes-like object. Це еквівалентно `BytesParser().parsebytes(s)`. Необов’язкові _class і policy інтерпретуються як конструктор класу `BytesParser`.

  Нове в версії 3.2.

  Змінено в версії 3.3: Видалено суворий аргумент. Додано ключове слово політика.

email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)

  Повертає дерево структури об’єкта повідомлення з відкритого двійкового файлу file object. Це еквівалентно `BytesParser().parse(fp)`. _class і policy інтерпретуються як конструктор класу `BytesParser`.

  Нове в версії 3.2.

  Змінено в версії 3.3: Видалено суворий аргумент. Додано ключове слово політика.

email.message_from_string(s, _class=None, *, policy=policy.compat32)

  Повертає структуру об’єкта повідомлення з рядка. Це еквівалентно `Parser().parsestr(s)`. _class і policy інтерпретуються як конструктор класу `Parser`.

  Змінено в версії 3.3: Видалено суворий аргумент. Додано ключове слово політика.

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

  Повертає дерево структури об’єкта повідомлення з відкритого file object. Це еквівалентно `Parser().parse(fp)`. _class і policy інтерпретуються як конструктор класу `Parser`.

  Змінено в версії 3.3: Видалено суворий аргумент. Додано ключове слово політика.

  Змінено в версії 3.6: _class за умовчанням використовує політику `message_factory`.

Ось приклад того, як можна використовувати `message_from_bytes()` в інтерактивному запиті Python:

    >>> import email
    >>> msg = email.message_from_bytes(myBytes)

## Додаткові нотатки

Ось деякі зауваження щодо семантики аналізу:

- Більшість повідомлень не типу multipart аналізуються як один об’єкт повідомлення з корисним навантаженням рядка. Ці об’єкти повернуть `False` для `is_multipart()`, а `iter_parts()` дасть порожній список.

- Усі повідомлення типу multipart аналізуватимуться як контейнерний об’єкт повідомлення зі списком об’єктів підповідомлення для їх корисного навантаження. Повідомлення зовнішнього контейнера поверне `True` для `is_multipart()`, а `iter_parts()` дасть список підчастин.

- Більшість повідомлень із типом вмісту message/* (наприклад, message/delivery-status і message/rfc822) також аналізуватимуться як об’єкт-контейнер, що містить корисне навантаження списку довжиною 1. Їхній метод `is_multipart()` поверне значення `True`. Єдиний елемент, отриманий `iter_parts()`, буде об’єктом підповідомлення.

- Деякі повідомлення, що не відповідають стандартам, можуть бути внутрішньо неузгодженими щодо їх multipart-edness. Такі повідомлення можуть мати заголовок Content-Type типу multipart, але їхній метод `is_multipart()` може повертати значення `False`. Якщо такі повідомлення були проаналізовані за допомогою `FeedParser`, вони матимуть екземпляр класу `MultipartInvariantViolationDefect` у своєму списку атрибутів defects. Перегляньте `email.errors` для деталей.