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

Источник: Lib/email/generator.py


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

Как и в случае с модулем 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 равно None (по умолчанию), для управления генерацией сообщений используется политика, связанная с объектом Message или EmailMessage, переданным в flatten. Подробнее о том, чем управляет policy, см. в разделе email.policy.

Added in version 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 равно 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 тип части non-text

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

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

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

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

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

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

Сноски