Документация Python неофициальный перевод
Содержание страницы

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 FeedParserFeedParser 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 класса ParserParser 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, поэтому семантика и результаты двух парсеров идентичны.