email.parser.md
1> **Источник:** https://python-all.ru/3.1/library/email.parser.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.1.2. [`email`](https://python-all.ru/3.1/library/email.html#module-email): Разбор сообщений электронной почты89Структуры объектов сообщений можно создать одним из двух способов: либо создать с нуля, создав экземпляры объектов [`Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message) и соединив их с помощью вызовов `attach()` и `set_payload()`, либо разобрать плоское текстовое представление сообщения.1011Пакет [`email`](https://python-all.ru/3.1/library/email.html#module-email) предоставляет стандартный парсер, который понимает большинство структур документов электронной почты, включая MIME-документы. Можно передать парсеру строку или файловый объект, и он вернет корневой экземпляр [`Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message) структуры объекта. Для простых сообщений, не являющихся MIME, полезная нагрузка этого корневого объекта, скорее всего, будет строкой, содержащей текст сообщения. Для MIME-сообщений корневой объект вернет `True` из своего метода `is_multipart()`, а подчасти можно получить с помощью методов `get_payload()` и `walk()`.1213На самом деле доступны два интерфейса парсера: классический API [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser) и инкрементальный API [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser). Классический API [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser) подходит, если весь текст сообщения находится в памяти в виде строки или если всё сообщение хранится в файле в файловой системе. [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser) больше подходит для ситуаций, когда сообщение читается из потока, который может блокироваться в ожидании дополнительных данных (например, чтение сообщения электронной почты из сокета). [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser) может потреблять и анализировать сообщение инкрементально, возвращая корневой объект только после закрытия парсера [\[1\]](https://python-all.ru/3.1/library/email.parser.html#id2).1415Обратите внимание, что парсер можно расширять ограниченными способами, и, конечно, можно реализовать собственный парсер полностью с нуля. Нет никакой магической связи между встроенным парсером пакета [`email`](https://python-all.ru/3.1/library/email.html#module-email) и классом [`Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message), поэтому ваш собственный парсер может создавать деревья объектов сообщений любым способом, который сочтёт необходимым.1617## 18.1.2.1. API FeedParser1819[`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser), импортируемый из модуля `email.feedparser`, предоставляет API, подходящий для инкрементального разбора сообщений электронной почты, например, когда текст сообщения читается из источника, который может блокироваться (например, сокет). [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser), конечно, можно использовать для разбора сообщения, полностью содержащегося в строке или файле, но для таких случаев может быть удобнее классический API [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser). Семантика и результаты работы двух парсеров API идентичны.2021API [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser) прост: создаёте экземпляр, подаёте ему текст, пока есть что подавать, затем закрываете парсер, чтобы получить корневой объект сообщения. [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser) чрезвычайно точен при разборе сообщений, соответствующих стандартам, и очень хорошо справляется с сообщениями, не соответствующими стандартам, предоставляя информацию о том, как сообщение было признано некорректным. Он заполняет атрибут *defects* объекта сообщения списком всех проблем, найденных в сообщении. Список дефектов, которые можно найти, приведён в модуле [`email.errors`](https://python-all.ru/3.1/library/email.errors.html#module-email.errors).2223Вот API для [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser):2425#### `class email.parser.FeedParser(_factory=email.message.Message)`2627Создаёт экземпляр [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser). Необязательный параметр *\_factory* – это вызываемый объект без аргументов, который будет вызываться всякий раз, когда потребуется новый объект сообщения. По умолчанию используется класс [`email.message.Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message).2829#### `feed(data)`3031Передаёт парсеру3233[`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser)3435дополнительные данные.3637*data*3839должна быть строкой, содержащей одну или несколько строк. Строки могут быть неполными, и4041[`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser)4243правильно склеит такие неполные строки. Строки в строке могут иметь любой из трёх распространённых концевых символов: возврат каретки, перевод строки или возврат каретки с переводом строки (они могут даже быть смешаны).4445#### `close()`4647Закрытие4849[`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser)5051завершает разбор всех ранее переданных данных и возвращает корневой объект сообщения. Поведение при попытке передать дополнительные данные закрытому5253[`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser)5455не определено.5657## 18.1.2.2. API класса Parser5859Класс [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser), импортируемый из модуля `email.parser`, предоставляет API, который можно использовать для разбора сообщения, когда полное содержимое сообщения доступно в виде строки или файла. Модуль `email.parser` также предоставляет второй класс, называемый `HeaderParser`, который можно использовать, если интересуют только заголовки сообщения. В этих ситуациях `HeaderParser` может работать значительно быстрее, так как он не пытается разобрать тело сообщения, а устанавливает полезную нагрузку как сырое тело в виде строки. `HeaderParser` имеет тот же API, что и класс [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser).6061#### `class email.parser.Parser(_class=email.message.Message, strict=None)`6263Конструктор класса [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser) принимает необязательный аргумент *\_class*. Это должна быть вызываемая фабрика (например, функция или класс), которая используется всякий раз, когда необходимо создать объект вложенного сообщения. По умолчанию используется [`Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message) (см. [`email.message`](https://python-all.ru/3.1/library/email.message.html#module-email.message)). Фабрика будет вызываться без аргументов.6465Необязательный флаг *strict* игнорируется.6667Устарело с версии 2.4: Поскольку класс [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser) является обратно совместимой обёрткой API вокруг появившегося в Python 2.4 [`FeedParser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.FeedParser), *весь* разбор фактически является нестрогим. Следует просто перестать передавать флаг *strict* конструктору [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser).6869Другие публичные методы [`Parser`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser):7071#### `parse(fp, headersonly=False)`7273Читает все данные из файлоподобного объекта *fp*, разбирает полученный текст и возвращает корневой объект сообщения. *fp* должен поддерживать как `readline()`, так и `read()` методы файлоподобных объектов.7475Текст, содержащийся в *fp*, должен быть отформатирован как блок заголовков в стиле [**RFC 2822**](https://python-all.ru/3.1/library/email.parser.html) и строк продолжения заголовков, возможно, с предшествующим заголовком конверта. Блок заголовков завершается либо концом данных, либо пустой строкой. За блоком заголовков следует тело сообщения (которое может содержать MIME-кодированные подчасти).7677Необязательный параметр *headersonly* работает так же, как в методе [`parse()`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser.parse).7879#### `parsestr(text, headersonly=False)`8081Аналогичен методу [`parse()`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser.parse), за исключением того, что принимает строковый объект вместо файлоподобного. Вызов этого метода для строки полностью эквивалентен предварительной обёртке *text* в экземпляр `StringIO` и последующему вызову [`parse()`](https://python-all.ru/3.1/library/email.parser.html#email.parser.Parser.parse).8283Необязательный параметр *headersonly* – это флаг, указывающий, нужно ли остановить разбор после чтения заголовков. Значение по умолчанию – `False`, то есть разбирается всё содержимое файла.8485Поскольку создание структуры объекта сообщения из строки или файлового объекта является очень распространённой задачей, для удобства предоставлены две функции. Они доступны в пространстве имён пакета верхнего уровня [`email`](https://python-all.ru/3.1/library/email.html#module-email).8687#### `email.message_from_string(s[, _class][, strict])`8889Возвращает структуру объекта сообщения из строки. Это полностью эквивалентно9091`Parser().parsestr(s)`9293. Необязательные аргументы9495*\_class*9697и9899*strict*100101интерпретируются так же, как в конструкторе класса102103`Parser`104105.106107#### `email.message_from_file(fp[, _class][, strict])`108109Возвращает дерево структуры объекта сообщения из открытого110111[*файлового объекта*](https://python-all.ru/3.1/glossary.html#term-file-object)112113. Это полностью эквивалентно114115`Parser().parse(fp)`116117. Необязательные аргументы118119*\_class*120121и122123*strict*124125интерпретируются так же, как в конструкторе класса126127`Parser`128129.130131Вот пример использования этого в интерактивном приглашении Python:132133```python134>>> import email135>>> msg = email.message_from_string(myString)136```137138## 18.1.2.3. Дополнительные примечания139140Вот некоторые замечания по семантике разбора:141142- Большинство сообщений, не являющихся *multipart*, разбираются как одно сообщение со строковой полезной нагрузкой. Такие объекты будут возвращать `False` для `is_multipart()`. Их метод `get_payload()` будет возвращать строковый объект.143- Все сообщения типа *multipart* разбираются как контейнерное сообщение со списком вложенных сообщений в качестве полезной нагрузки. Внешнее контейнерное сообщение будет возвращать `True` для `is_multipart()`, а его метод `get_payload()` будет возвращать список подчастей [`Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message).144- Большинство сообщений с типом содержимого *message/\** (например,\\n*message/delivery-status* и *message/rfc822*) также будут\\nразобраны как объект-контейнер, содержащий полезную нагрузку в виде списка длиной 1. Их\\nметод `is_multipart()` будет возвращать `True`. Единственный элемент в\\nсписке полезной нагрузки будет объектом подсообщения.145- Некоторые сообщения, не соответствующие стандартам, могут быть внутренне непоследовательны в отношении\\nсвоей *многокомпонентности*. Такие сообщения могут иметь\\nзаголовок *Content-Type* типа *multipart*, но их\\nметод `is_multipart()` может возвращать `False`. Если такие сообщения были разобраны\\nс помощью `FeedParser`, они будут содержать экземпляр класса\\n`MultipartInvariantViolationDefect` в своем списке атрибутов *defects*.\\nПодробнее см. [`email.errors`](https://python-all.ru/3.1/library/email.errors.html#module-email.errors).146147Сноски148149| [\[1\]](https://python-all.ru/3.1/library/email.parser.html#id1) | Начиная с версии 3.0 пакета email, представленной в Python 2.4, классический\\n`Parser` был перереализован на основе `FeedParser`, поэтому\\nсемантика и результаты двух анализаторов идентичны. |150| --- | --- |151