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

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

API анализатора обратной связи

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

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

Вот API для BytesFeedParser:

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

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

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

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

Добавлено в версии 3.2.

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

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

feed(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 всегда должно быть указано; Значение по умолчанию изменится на email.policy.default в будущей версии Python.

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

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

parse(fp, headersonly=False)

Считайте все данные из объекта, подобного двоичному файлу fp, анализируйте полученные байты и возвращайте объект message. 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().

Необязательный headersonly используется так же, как и в методе parse().

Добавлено в версии 3.2.

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

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

Добавлено в версии 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(), за исключением того, что он использует объект string вместо объекта, подобного файлу. Вызов этого метода для строки эквивалентен переносу text в экземпляр StringIO и вызову parse().

Необязательный headersonly используется так же, как и в методе parse().

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

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

Поскольку создание структуры объекта сообщения из строки или файлового объекта является такой распространенной задачей, для удобства предусмотрены четыре функции. Они доступны в пространстве имен пакетов верхнего уровня email.

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

Возвращает структуру объекта message из bytes-like object. Это эквивалентно BytesParser().parsebytes(s). Необязательные значения _class и policy интерпретируются как в конструкторе класса BytesParser.

Добавлено в версии 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.

Добавлено в версии 3.2.

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

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

Возвращает структуру объекта message из строки. Это эквивалентно 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)  

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

Вот несколько замечаний по семантике синтаксического анализа:

  • Большинство сообщений, не относящихся к типу :mimetype:multipart, анализируются как единый объект message с полезной нагрузкой string. Эти объекты вернут False для is_multipart(), а iter_parts() выдаст пустой список.

  • Все сообщения типа multipart будут проанализированы как объект сообщения-контейнера со списком объектов вложенных сообщений для их полезной нагрузки. Сообщение внешнего контейнера вернет True для is_multipart(), а iter_parts() выдаст список подразделов.

  • Большинство сообщений с типом содержимого message/* (например, message/delivery-status и message/rfc822) также будут проанализированы как объект-контейнер, содержащий полезную нагрузку list длиной 1. Их метод is_multipart() вернет True. Единственный элемент, полученный с помощью iter_parts(), будет объектом вложенного сообщения.

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

Вернуться на верх