email.parser: Разбор сообщений электронной почты

Источник: 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 API наиболее полезен, если весь текст сообщения находится в памяти или если все сообщение хранится в файле на файловой системе. API FeedParser больше подходит для чтения сообщения из потока, который может заблокироваться в ожидании дополнительного ввода (например, чтение сообщения электронной почты из сокета). FeedParser может потреблять и разбирать сообщение постепенно, и возвращает корневой объект только после закрытия парсера.

Обратите внимание, что парсер может быть расширен ограниченными способами, и, конечно, вы можете реализовать свой собственный парсер полностью с нуля. Вся логика, связывающая парсер из пакета email и класс EmailMessage, воплощена в классе Policy, поэтому пользовательский парсер может создавать деревья объектов сообщений любым способом, который сочтет нужным, реализуя собственные версии соответствующих методов Policy.

API FeedParser

Модуль BytesFeedParser, импортированный из модуля email.feedparser, предоставляет API, позволяющий выполнять инкрементный разбор почтовых сообщений, например, при чтении текста почтового сообщения из источника, который может блокироваться (например, сокета). Конечно, BytesFeedParser можно использовать для разбора почтового сообщения, полностью содержащегося в bytes-like object, строке или файле, но BytesParser может быть более удобным для такого использования. API может быть более удобным для таких случаев. Семантика и результаты работы двух API парсеров идентичны.

API BytesFeedParser прост: вы создаете экземпляр, скармливаете ему кучу байтов, пока больше не останется, а затем закрываете парсер, чтобы получить корневой объект сообщения. BytesFeedParser очень точен при разборе сообщений, соответствующих стандартам, и отлично справляется с разбором сообщений, не соответствующих стандартам, предоставляя информацию о том, как сообщение было признано нерабочим. Он заполняет атрибут defects объекта сообщения списком всех проблем, которые он обнаружил в сообщении. Список дефектов, которые он может найти, см. в модуле email.errors.

Вот API для BytesFeedParser:

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

Создает экземпляр BytesFeedParser. Необязательная _factory - это неаргументированный вызываемый объект; если он не указан, используйте message_factory из policy. Вызывайте _factory всякий раз, когда требуется новый объект сообщения.

Если указана policy, используйте указанные в ней правила для обновления представления сообщения. Если policy не задана, используйте политику compat32, которая поддерживает обратную совместимость с версией почтового пакета Python 3.2 и предоставляет Message в качестве фабрики по умолчанию. Все остальные политики предоставляют EmailMessage в качестве _фабрики по умолчанию. Для получения дополнительной информации о том, чем еще управляет policy, смотрите документацию по policy.

Примечание: Ключевое слово policy всегда должно быть указано; в будущих версиях Python значение по умолчанию будет изменено на email.policy.default.

Added in version 3.2.

Изменено в версии 3.3: Добавлено ключевое слово policy.

Изменено в версии 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: Добавлено ключевое слово policy.

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.

Примечание: Ключевое слово policy всегда должно быть указано; в будущих версиях Python значение по умолчанию будет изменено на email.policy.default.

Изменено в версии 3.3: Удален аргумент strict, который был устаревшим в версии 2.4. Добавлено ключевое слово policy.

Изменено в версии 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-like object эквивалентен тому, чтобы сначала завернуть байты в экземпляр BytesIO и вызвать parse().

Опционально лично - как при использовании метода parse().

Added in version 3.2.

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

Точно так же, как и BytesParser, за исключением того, что по умолчанию для headersonly используется значение True.

Added in version 3.3.

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

Этот класс параллелен BytesParser, но работает со строковым вводом.

Изменено в версии 3.3: Удален аргумент strict. Добавлено ключевое слово policy.

Изменено в версии 3.6: По умолчанию для _class используется политика message_factory.

parse(fp, headersonly=False)

Прочитайте все данные из файлоподобного объекта fp, работающего в текстовом режиме, разберите полученный текст и верните корневой объект сообщения. fp должен поддерживать оба метода readline() и read() для файлоподобных объектов.

За исключением требования текстового режима, этот метод работает так же, как BytesParser.parse().

parsestr(text, headersonly=False)

Аналогичен методу parse(), только вместо файлоподобного объекта принимает строковый объект. Вызов этого метода для строки эквивалентен тому, чтобы сначала обернуть text в экземпляр StringIO и вызвать parse().

Опционально лично - как при использовании метода 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.

Added in version 3.2.

Изменено в версии 3.3: Удален аргумент strict. Добавлено ключевое слово policy.

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

Возвращает дерево структуры объектов сообщений из открытого двоичного file object. Это эквивалентно BytesParser().parse(fp). _class и policy интерпретируются как в конструкторе класса BytesParser.

Added in version 3.2.

Изменено в версии 3.3: Удален аргумент strict. Добавлено ключевое слово policy.

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

Возвращает структуру объекта сообщения из строки. Это эквивалентно Parser().parsestr(s). _class и policy интерпретируются как в конструкторе класса Parser.

Изменено в версии 3.3: Удален аргумент strict. Добавлено ключевое слово policy.

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

Возвращает дерево структуры объектов сообщений из открытого file object. Это эквивалентно Parser().parse(fp). _class и policy интерпретируются как в конструкторе класса Parser.

Изменено в версии 3.3: Удален аргумент strict. Добавлено ключевое слово policy.

Изменено в версии 3.6: По умолчанию для _class используется политика message_factory.

Вот пример того, как можно использовать message_from_bytes() в интерактивном приглашении Python:

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

Дополнительные примечания

Вот некоторые замечания по семантике разбора:

  • Большинство сообщений типа non-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-едности. Такие сообщения могут иметь заголовок Content-Type типа multipart, но их метод is_multipart() может возвращать False. Если такие сообщения были разобраны с помощью FeedParser, то в списке атрибутов defects у них будет экземпляр класса MultipartInvariantViolationDefect. Подробности см. в разделе email.errors.