Содержание страницы
19.1.2. email.parser: Разбор сообщений электронной почты¶email.parser: Parsing email messages
Исходный код: Lib/email/parser.py
Структуры объектов сообщений можно создать двумя способами: создать с нуля, создавая объекты 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 нет никакой магической связи, поэтому ваш собственный анализатор может создавать деревья объектов сообщений любым подходящим ему способом.
19.1.2.1. 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=email.message.Message, *, policy=policy.compat32)¶ Создаёт экземпляр
FeedParser. Необязательный параметр _factory – это вызываемый объект без аргументов, который будет вызываться при необходимости создания нового объекта сообщения. По умолчанию используется классemail.message.Message.Если указан policy (он должен быть экземпляром класса
policy), используйте заданные им правила для обновления представления сообщения. Если policy не задан, применяется политикаcompat32, которая обеспечивает обратную совместимость с версией пакета email для Python 3.2. Дополнительную информацию см. в документацииpolicy.Изменено в версии 3.3: Добавлен параметр policy.
-
feed(data)¶ Передаёт дополнительные данные анализатору
FeedParser. data должна быть строкой, содержащей одну или несколько строк. Строки могут быть неполными, иFeedParserправильно соберёт такие части строк. Строки могут иметь любые из трёх распространённых окончаний: возврат каретки, перевод строки или возврат каретки и перевод строки (допускается смешивание).
-
close()¶ Закрытие
FeedParserзавершает разбор всех ранее переданных данных и возвращает корневой объект сообщения. Что произойдёт при передаче дополнительных данных закрытомуFeedParser, не определено.
-
-
class
email.parser.BytesFeedParser(_factory=email.message.Message)¶ Работает точно так же, как
FeedParser, за исключением того, что входные данные для методаfeed()должны быть байтами, а не строкой.Новое в версии 3.2.
19.1.2.2. API класса Parser¶Parser class API
Класс Parser, импортируемый из модуля email.parser, предоставляет API для разбора сообщения, когда полное содержимое сообщения доступно в виде строки или файла. Модуль email.parser также предоставляет анализаторы только для заголовков, называемые HeaderParser и BytesHeaderParser, которые можно использовать, если интересуют только заголовки сообщения. HeaderParser и BytesHeaderParser могут быть значительно быстрее в таких ситуациях, поскольку они не пытаются разобрать тело сообщения, а вместо этого устанавливают полезную нагрузку в виде необработанного тела как строку. Их API совпадает с API классов Parser и BytesParser.
Новое в версии 3.3: Класс BytesHeaderParser.
-
class
email.parser.Parser(_class=email.message.Message, *, policy=policy.compat32)¶ Конструктор класса
Parserпринимает необязательный аргумент _class. Это должен быть вызываемый объект-фабрика (например, функция или класс), используемый при необходимости создания подобъекта сообщения. По умолчанию используетсяMessage(см.email.message). Фабрика вызывается без аргументов.Если указан policy (он должен быть экземпляром класса
policy), используйте заданные им правила для обновления представления сообщения. Если policy не задан, применяется политикаcompat32, которая обеспечивает обратную совместимость с версией пакета email для Python 3.2. Дополнительную информацию см. в документацииpolicy.Изменено в версии 3.3: Удалён аргумент strict, устаревший в версии 2.4. Добавлен параметр policy.
Другие открытые методы
Parser:-
parse(fp, headersonly=False)¶ Читает все данные из файлоподобного объекта fp, разбирает полученный текст и возвращает корневой объект сообщения. fp должен поддерживать как метод
readline(), так и методread(), характерные для файлоподобных объектов.Текст, содержащийся в fp, должен быть отформатирован как блок заголовков и строк продолжения заголовков в стиле RFC 2822, при необходимости перед которым может идти конвертный заголовок. Блок заголовков завершается либо концом данных, либо пустой строкой. После блока заголовков следует тело сообщения (которое может содержать MIME-кодированные вложенные части).
Необязательный параметр headersonly – флаг, указывающий, следует ли остановить разбор после чтения заголовков. По умолчанию
False, то есть разбирается всё содержимое файла.
-
parsestr(text, headersonly=False)¶ Аналогичен методу
parse(), за исключением того, что принимает строковый объект вместо файлоподобного. Вызов этого метода для строки эквивалентен предварительной обёртке text в экземплярStringIOс последующим вызовомparse().Необязательный параметр headersonly действует так же, как в методе
parse().
-
-
class
email.parser.BytesParser(_class=email.message.Message, *, policy=policy.compat32)¶ Этот класс полностью аналогичен
Parser, но работает с байтовыми входными данными. Аргументы _class и strict интерпретируются так же, как в конструктореParser.Если указан policy (он должен быть экземпляром класса
policy), используйте заданные им правила для обновления представления сообщения. Если policy не задан, применяется политикаcompat32, которая обеспечивает обратную совместимость с версией пакета email для Python 3.2. Дополнительную информацию см. в документацииpolicy.Изменено в версии 3.3: Удалён аргумент strict. Добавлен ключевой аргумент policy.
-
parse(fp, headersonly=False)¶ Читает все данные из двоичного файлоподобного объекта fp, разбирает полученные байты и возвращает объект сообщения. fp должен поддерживать как метод
readline(), так и методread()файлоподобных объектов.Содержащиеся в fp байты должны быть отформатированы как блок заголовков в стиле RFC 2822 и строк продолжения заголовков, необязательно перед которыми может идти заголовок конверта. Блок заголовков завершается либо концом данных, либо пустой строкой. За блоком заголовков следует тело сообщения (которое может содержать MIME-кодированные подчасти, включая подчасти с Content-Transfer-Encoding, равным
8bit).Необязательный параметр headersonly – флаг, указывающий, следует ли остановить разбор после чтения заголовков. По умолчанию
False, то есть разбирается всё содержимое файла.
-
parsebytes(text, headersonly=False)¶ Аналогично методу
parse(), за исключением того, что принимает байтоподобный объект вместо файлоподобного объекта. Вызов этого метода эквивалентен предварительной обёртке text в экземплярBytesIOи последующему вызовуparse().Необязательный параметр headersonly действует так же, как в методе
parse().
Новое в версии 3.2.
-
Поскольку создание структуры объекта сообщения из строки или файлового объекта является распространённой задачей, для удобства предоставляются четыре функции. Они доступны
в пространстве имён пакета верхнего уровня email.
-
email.message_from_string(s, _class=email.message.Message, *, policy=policy.compat32)¶ Возвращает структуру объекта сообщения из строки. Это в точности эквивалентно
Parser().parsestr(s). _class и policy интерпретируются так же, как в конструкторе классаParser.Изменено в версии 3.3: Удалён аргумент strict. Добавлен ключевой аргумент policy.
-
email.message_from_bytes(s, _class=email.message.Message, *, policy=policy.compat32)¶ Возвращает структуру объекта сообщения из байтоподобного объекта. Это в точности эквивалентно
BytesParser().parsebytes(s). Необязательные _class и strict интерпретируются так же, как в конструкторе классаParser.Новое в версии 3.2.
Изменено в версии 3.3: Удалён аргумент strict. Добавлен ключевой аргумент policy.
-
email.message_from_file(fp, _class=email.message.Message, *, policy=policy.compat32)¶ Возвращает дерево структуры объекта сообщения из открытого файлового объекта. Это в точности эквивалентно
Parser().parse(fp). _class и policy интерпретируются так же, как в конструкторе классаParser.Изменено в версии 3.3: Удалён аргумент strict. Добавлен ключевой аргумент policy.
-
email.message_from_binary_file(fp, _class=email.message.Message, *, policy=policy.compat32)¶ Возвращает дерево структуры объекта сообщения из открытого двоичного файлового объекта. Это в точности эквивалентно
BytesParser().parse(fp). _class и policy интерпретируются так же, как в конструкторе классаParser.Новое в версии 3.2.
Изменено в версии 3.3: Удалён аргумент strict. Добавлен ключевой аргумент policy.
Вот пример использования этого в интерактивном приглашении Python:
>>> import email
>>> msg = email.message_from_string(myString)
19.1.2.3. Дополнительные примечания¶Additional notes
Вот некоторые замечания по семантике разбора:
- Большинство сообщений, не являющихся multipart, разбираются как одиночный объект сообщения со строковым содержимым. Такие объекты будут возвращать
Falseдляis_multipart(). Их методget_payload()будет возвращать строковый объект. - Все сообщения типа multipart будут разбираться как объект-контейнер со списком объектов-подсообщений в качестве содержимого. Внешний контейнер будет возвращать
Trueдляis_multipart(), а его методget_payload()вернёт список изMessageподчастей. - Большинство сообщений с типом содержимого message/* (например, message/delivery-status и message/rfc822) также будут разбираться как объект-контейнер, содержащий полезную нагрузку в виде списка длиной 1. Их метод
is_multipart()вернётTrue. Единственный элемент в списке будет объектом-подсообщением. - Некоторые сообщения, не соответствующие стандартам, могут быть внутренне несогласованы относительно своей multipart-ности. Такие сообщения могут иметь заголовок Content-Type типа multipart, но их метод
is_multipart()может возвращатьFalse. Если такие сообщения были разобраны с помощьюFeedParser, они будут содержать экземпляр классаMultipartInvariantViolationDefectв списке атрибутов defects. Подробнее см.email.errors.
Сноски
| [1] | Начиная с версии 3.0 пакета email, представленной в Python 2.4, классический Parser был перереализован на основе FeedParser, поэтому семантика и результаты двух парсеров идентичны. |