Содержание страницы
email: Разбор сообщений электронной почты¶email: Parsing email messages
Структуры объектов сообщений можно создать двумя способами: либо с нуля, создавая экземпляры Message и связывая их вызовами attach() и set_payload(), либо путём разбора плоского текстового представления сообщения электронной почты.
Пакет email предоставляет стандартный анализатор, который понимает большинство структур документов электронной почты, включая MIME-документы. Анализатору можно передать строку или файловый объект, и он вернёт корневой экземпляр Message в структуре объекта. Для простых (не MIME) сообщений полезная нагрузка корневого объекта, скорее всего, будет строкой с текстом сообщения. Для MIME-сообщений корневой объект вернёт True от своего метода is_multipart(), а к вложенным частям можно обращаться через методы get_payload() и walk().
На самом деле доступны два интерфейса парсера: классический API Parser и инкрементальный API FeedParser. Классический API Parser подходит, если весь текст сообщения находится в памяти в виде строки или если всё сообщение хранится в файле в файловой системе. FeedParser больше подходит для ситуаций, когда сообщение читается из потока, который может блокироваться в ожидании дополнительных данных (например, чтение сообщения электронной почты из сокета). FeedParser может потреблять и анализировать сообщение инкрементально, возвращая корневой объект только после закрытия парсера [1].
Обратите внимание, что анализатор можно расширять ограниченными способами, и конечно, можно реализовать собственный анализатор полностью с нуля. Между встроенным анализатором пакета email и классом Message нет никакой магической связи, поэтому ваш собственный анализатор может создавать деревья объектов сообщений любым способом, который сочтёт необходимым.
API FeedParser¶FeedParser API
FeedParser, импортируемый из модуля email.feedparser, предоставляет API, подходящий для инкрементального разбора сообщений электронной почты, например, когда текст сообщения читается из источника, который может блокироваться (например, сокет). FeedParser, конечно, можно использовать для разбора сообщения, полностью содержащегося в строке или файле, но для таких случаев может быть удобнее классический API Parser. Семантика и результаты работы двух парсеров API идентичны.
API FeedParser прост: создаёте экземпляр, подаёте ему текст, пока есть что подавать, затем закрываете парсер, чтобы получить корневой объект сообщения. FeedParser чрезвычайно точен при разборе сообщений, соответствующих стандартам, и очень хорошо справляется с сообщениями, не соответствующими стандартам, предоставляя информацию о том, как сообщение было признано некорректным. Он заполняет атрибут defects объекта сообщения списком всех проблем, найденных в сообщении. Список дефектов, которые можно найти, приведён в модуле email.errors.
Вот API для FeedParser:
- class email.parser.FeedParser([_factory])¶
Создаёт экземпляр FeedParser. Необязательный параметр _factory – это вызываемый объект без аргументов, который будет вызываться всякий раз, когда потребуется новый объект сообщения. По умолчанию используется класс email.message.Message.
- feed(data)¶
- Передаёт парсеру FeedParser дополнительные данные. data должна быть строкой, содержащей одну или несколько строк. Строки могут быть неполными, и FeedParser правильно склеит такие неполные строки. Строки в строке могут иметь любой из трёх распространённых концевых символов: возврат каретки, перевод строки или возврат каретки с переводом строки (они могут даже быть смешаны).
- close()¶
- Закрытие FeedParser завершает разбор всех ранее переданных данных и возвращает корневой объект сообщения. Поведение при попытке передать дополнительные данные закрытому FeedParser не определено.
API класса Parser¶Parser class API
Класс Parser, импортируемый из модуля email.parser, предоставляет API, который можно использовать для разбора сообщения, когда полное содержимое сообщения доступно в виде строки или файла. Модуль email.parser также предоставляет второй класс, называемый HeaderParser, который можно использовать, если интересуют только заголовки сообщения. В этих ситуациях HeaderParser может работать значительно быстрее, так как он не пытается разобрать тело сообщения, а устанавливает полезную нагрузку как сырое тело в виде строки. HeaderParser имеет тот же API, что и класс Parser.
- class email.parser.Parser([_class])¶
Конструктор класса Parser принимает необязательный аргумент _class. Это должна быть вызываемая фабрика (например, функция или класс), и она используется всякий раз, когда необходимо создать подобъект сообщения. По умолчанию используется Message (см. email.message). Фабрика вызывается без аргументов.
Необязательный флаг strict игнорируется.
Устарело с версии 2.4: Поскольку класс Parser является обратно совместимой обёрткой API вокруг появившегося в Python 2.4 FeedParser, весь разбор фактически является нестрогим. Следует просто перестать передавать флаг strict конструктору Parser.
Другие публичные методы Parser:
- parse(fp[, headersonly])¶
Читает все данные из файлоподобного объекта fp, разбирает полученный текст и возвращает корневой объект сообщения. fp должен поддерживать как readline(), так и read() методы файлоподобных объектов.
Текст, содержащийся в fp, должен быть отформатирован как блок заголовков в стиле RFC 2822 и строк продолжения заголовков, возможно, с предшествующим заголовком конверта. Блок заголовков завершается либо концом данных, либо пустой строкой. За блоком заголовков следует тело сообщения (которое может содержать MIME-кодированные подчасти).
Необязательный параметр headersonly работает так же, как в методе parse().
- parsestr(text[, headersonly])¶
Аналогичен методу parse(), за исключением того, что принимает строковый объект вместо файлоподобного. Вызов этого метода для строки полностью эквивалентен предварительной обёртке text в экземпляр StringIO и последующему вызову parse().
Необязательный параметр headersonly – это флаг, указывающий, нужно ли остановить разбор после чтения заголовков. Значение по умолчанию – False, то есть разбирается всё содержимое файла.
Поскольку создание структуры объекта сообщения из строки или файлового объекта является очень распространённой задачей, для удобства предоставлены две функции. Они доступны в пространстве имён пакета верхнего уровня email.
- email.message_from_string(s[, _class[, strict]])¶
- Возвращает структуру объекта сообщения из строки. Это полностью эквивалентно Parser().parsestr(s). Необязательные аргументы _class и strict интерпретируются так же, как в конструкторе класса Parser.
- email.message_from_file(fp[, _class[, strict]])¶
- Возвращает дерево структуры объекта сообщения из открытого файлового объекта. Это полностью эквивалентно Parser().parse(fp). Необязательные аргументы _class и strict интерпретируются так же, как в конструкторе класса Parser.
Вот пример использования этого в интерактивном приглашении Python:
>>> import email
>>> msg = email.message_from_string(myString)
Дополнительные примечания¶Additional notes
Вот некоторые замечания по семантике разбора:
- Большинство сообщений, не являющихся multipart, разбираются как одно сообщение со строковой полезной нагрузкой. Такие объекты будут возвращать False для is_multipart(). Их метод get_payload() будет возвращать строковый объект.
- Все сообщения типа multipart будут разобраны как контейнерное сообщение со списком подобъектов сообщений в качестве полезной нагрузки. Внешнее контейнерное сообщение вернёт True для is_multipart(), а его метод get_payload() вернёт список вложенных частей Message.
- Большинство сообщений с типом содержимого message/* (например,\nmessage/delivery-status и message/rfc822) также будут\nразобраны как объект-контейнер, содержащий полезную нагрузку в виде списка длиной 1. Их\nметод is_multipart() будет возвращать True. Единственный элемент в\nсписке полезной нагрузки будет объектом подсообщения.
- Некоторые сообщения, не соответствующие стандартам, могут быть внутренне непоследовательны в отношении\nсвоей многокомпонентности. Такие сообщения могут иметь\nзаголовок Content-Type типа multipart, но их\nметод is_multipart() может возвращать False. Если такие сообщения были разобраны\nс помощью FeedParser, они будут содержать экземпляр класса\nMultipartInvariantViolationDefect в своем списке атрибутов defects.\nПодробнее см. email.errors.
Сноски
| [1] | Начиная с версии 3.0 пакета email, представленной в Python 2.4, классический\nParser был перереализован на основе FeedParser, поэтому\nсемантика и результаты двух анализаторов идентичны. |