email.generator: Генерация MIME-документов

Исходный код: Lib/email/generator.py.


Одной из наиболее распространенных задач является генерация плоской (сериализованной) версии почтового сообщения, представленной структурой объекта message. Это необходимо сделать, если вы хотите отправить сообщение через smtplib.SMTP.sendmail() или модуль nntplib, или вывести сообщение на консоль. Получение объектной структуры сообщения и создание сериализованного представления - это работа классов-генераторов.

Как и в случае с модулем email.parser, вы не ограничены функциональностью поставляемого генератора; вы можете написать его с нуля самостоятельно. Однако поставляемый в комплекте генератор знает, как генерировать большинство сообщений электронной почты в соответствии со стандартами, должен отлично обрабатывать сообщения электронной почты MIME и не-MIME, и разработан таким образом, что операции разбора и генерации, ориентированные на байты, являются инверсными, предполагая, что для обеих операций используется один и тот же не преобразующий policy. То есть, разбор сериализованного потока байтов с помощью класса BytesParser, а затем регенерация сериализованного потока байтов с помощью BytesGenerator должны дать результат, идентичный входному 1. (С другой стороны, использование генератора на построенном программой EmailMessage может привести к изменениям в объекте EmailMessage по мере заполнения значений по умолчанию).

Класс Generator можно использовать для преобразования сообщения в текстовое (в отличие от двоичного) сериализованное представление, но поскольку Unicode не может представлять двоичные данные напрямую, сообщение необходимо преобразовать в нечто, содержащее только символы ASCII, используя стандартные методы кодирования электронной почты RFC Content Transfer Encoding для кодирования сообщений электронной почты для передачи по каналам, которые не являются «8-битовыми чистыми».

Для обеспечения воспроизводимой обработки SMIME-подписанных сообщений Generator отключает сворачивание заголовков для частей сообщения типа multipart/signed и всех подчастей.

class email.generator.BytesGenerator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

Возвращает объект BytesGenerator, который запишет любое сообщение, предоставленное в методе flatten(), или любой суррогатно-кодированный текст, предоставленный в методе write(), в file-like object outfp. outfp должен поддерживать метод write, принимающий двоичные данные.

Если необязательное значение mangle_from_ равно True, поставьте символ > перед любой строкой в теле, которая начинается с точной строки "From ", то есть From, за которой следует пробел в начале строки. mangle_from_ по умолчанию соответствует значению параметра mangle_from_, заданного в policy (который равен True для политики compat32 и False для всех остальных). mangle_from_ предназначен для использования, когда сообщения хранятся в формате unix mbox (см. mailbox и WHY THE CONTENT-LENGTH FORMAT IS BAD).

Если maxheaderlen не None, переверните все строки заголовков, длина которых превышает maxheaderlen, или, если 0, не перевертывайте заголовки. Если manheaderlen равен None (по умолчанию), оберните заголовки и другие строки сообщения в соответствии с настройками policy.

Если указана policy, используйте эту политику для управления генерацией сообщений. Если policy равно None (по умолчанию), то для управления генерацией сообщений используется политика, связанная с объектом Message или EmailMessage, переданным в flatten. Подробнее о том, чем управляет policy, смотрите в email.policy.

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

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

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

flatten(msg, unixfrom=False, linesep=None)

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

Если опция policy cte_type равна 8bit (по умолчанию), скопируйте любые заголовки в исходном разобранном сообщении, которые не были изменены, на выход с воспроизведением всех байтов с установленным старшим битом, как в оригинале, и сохраните не ASCII Content-Transfer-Encoding любых частей тела, которые имеют их. Если cte_type является 7bit, преобразуйте байты с установленным старшим битом по мере необходимости, используя ASCII-совместимый Content-Transfer-Encoding. То есть, преобразуйте части с не ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) в ASCII-совместимые Content-Transfer-Encoding, и закодируйте RFC-недействительные не ASCII байты в заголовках, используя набор символов MIME unknown-8bit, тем самым делая их RFC-совместимыми.

Если unixfrom равно True, выведите разделитель заголовка конверта, используемый форматом почтового ящика Unix (см. mailbox), перед первым из заголовков RFC 5322 корневого объекта сообщения. Если корневой объект не имеет заголовка конверта, создайте стандартный заголовок. По умолчанию используется False. Обратите внимание, что для подчастей заголовок конверта никогда не печатается.

Если linesep не None, используйте его в качестве символа-разделителя между всеми строками сплющенного сообщения. Если linesep равен None (значение по умолчанию), используйте значение, указанное в policy.

clone(fp)

Возвращает независимый клон данного экземпляра BytesGenerator с точно такими же настройками опций и fp в качестве нового outfp.

write(s)

Закодируйте s, используя кодек ASCII и обработчик ошибок surrogateescape, и передайте его в метод write метода outfp, переданного в конструктор BytesGenerator.

В качестве удобства EmailMessage предоставляет методы as_bytes() и bytes(aMessage) (они же __bytes__()), которые упрощают генерацию сериализованного двоичного представления объекта сообщения. Для получения более подробной информации смотрите email.message.

Поскольку строки не могут представлять двоичные данные, класс Generator должен преобразовать любые двоичные данные в любом сообщении, которое он сплющивает, в формат, совместимый с ASCII, путем преобразования их в Content-Transfer_Encoding, совместимый с ASCII. Используя терминологию почтовых RFC, вы можете представить это как Generator сериализацию в поток ввода-вывода, который не является «8-битным чистым». Другими словами, большинство приложений захотят использовать BytesGenerator, а не Generator.

class email.generator.Generator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

Возвращает объект Generator, который запишет любое сообщение, предоставленное в методе flatten(), или любой текст, предоставленный в методе write(), в file-like object outfp. outfp должен поддерживать метод write, принимающий строковые данные.

Если необязательное значение mangle_from_ равно True, поставьте символ > перед любой строкой в теле, которая начинается с точной строки "From ", то есть From, за которой следует пробел в начале строки. mangle_from_ по умолчанию соответствует значению параметра mangle_from_, заданного в policy (который равен True для политики compat32 и False для всех остальных). mangle_from_ предназначен для использования, когда сообщения хранятся в формате unix mbox (см. mailbox и WHY THE CONTENT-LENGTH FORMAT IS BAD).

Если maxheaderlen не None, переверните все строки заголовков, длина которых превышает maxheaderlen, или, если 0, не перевертывайте заголовки. Если manheaderlen равен None (по умолчанию), оберните заголовки и другие строки сообщения в соответствии с настройками policy.

Если указана policy, используйте эту политику для управления генерацией сообщений. Если policy равно None (по умолчанию), то для управления генерацией сообщений используется политика, связанная с объектом Message или EmailMessage, переданным в flatten. Подробнее о том, чем управляет policy, смотрите в email.policy.

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

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

flatten(msg, unixfrom=False, linesep=None)

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

Если опция policy cte_type имеет значение 8bit, создайте сообщение, как если бы опция была установлена в значение 7bit. (Это необходимо, поскольку строки не могут представлять байты, отличные от ASCII.) Преобразуйте все байты с установленным старшим битом по мере необходимости, используя ASCII-совместимый Content-Transfer-Encoding. То есть, преобразуйте части с не-ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) в ASCII-совместимые Content-Transfer-Encoding, и закодируйте RFC-недействительные не-ASCII байты в заголовках, используя набор символов MIME unknown-8bit, тем самым делая их RFC-совместимыми.

Если unixfrom равно True, выведите разделитель заголовка конверта, используемый форматом почтового ящика Unix (см. mailbox), перед первым из заголовков RFC 5322 корневого объекта сообщения. Если корневой объект не имеет заголовка конверта, создайте стандартный заголовок. По умолчанию используется False. Обратите внимание, что для подчастей заголовок конверта никогда не печатается.

Если linesep не None, используйте его в качестве символа-разделителя между всеми строками сплющенного сообщения. Если linesep равен None (значение по умолчанию), используйте значение, указанное в policy.

Изменено в версии 3.2: Добавлена поддержка повторного кодирования тел сообщений 8bit и аргумент linesep.

clone(fp)

Возвращает независимый клон данного экземпляра Generator с точно такими же опциями и fp в качестве нового outfp.

write(s)

Запишите s в метод write метода outfp, переданного в конструктор Generator. Это обеспечивает достаточно файлоподобный API для использования экземпляров Generator в функции print().

В качестве удобства EmailMessage предоставляет методы as_string() и str(aMessage) (они же __str__()), которые упрощают генерацию форматированного строкового представления объекта сообщения. Для получения более подробной информации смотрите email.message.

Модуль email.generator также предоставляет производный класс DecodedGenerator, который похож на базовый класс Generator, за исключением того, что нечасти text не сериализуются, а вместо этого представляются в выходном потоке строкой, полученной из шаблона, заполненного информацией о части.

class email.generator.DecodedGenerator(outfp, mangle_from_=None, maxheaderlen=None, fmt=None, *, policy=None)

Действует как Generator, за исключением того, что для любого подраздела сообщения, переданного в Generator.flatten(), если подраздел имеет основной тип text, печатает декодированную полезную нагрузку подраздела, а если основной тип не text, вместо печати заполняет строку fmt, используя информацию из части, и печатает полученную заполненную строку.

Чтобы заполнить fmt, выполните fmt % part_info, где part_info - словарь, состоящий из следующих ключей и значений:

  • type – Полный MIME тип нечасти text

  • maintype – Основной MIME тип нечасти text

  • subtype – Sub-MIME тип нечасти text

  • filename – Имя файла неtext части

  • description – Описание, связанное с неtext частью

  • encoding – Кодировка передачи содержимого нечасти text

Если fmt равно None, используйте следующий fmt по умолчанию:

«[Нетекстовая (%(type)s) часть сообщения опущена, имя файла %(filename)s]».

Необязательные _mangle_from_ и maxheaderlen - как у базового класса Generator.

Сноски

1

Это утверждение предполагает, что вы используете соответствующую настройку для unixfrom, и что нет настроек policy, требующих автоматической корректировки (например, refold_source должен быть none, что не является значением по умолчанию). Это также не на 100% верно, так как если сообщение не соответствует стандартам RFC, то иногда информация о точном оригинальном тексте теряется при восстановлении ошибок парсинга. Задача состоит в том, чтобы исправить эти крайние случаи, когда это возможно.

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