email.generator: Создание MIME документов


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

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

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

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

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

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

Если необязательный mangle_from_ равен True, поместите символ > перед любой строкой в теле, начинающейся с точной строки "From ", т. е. From, за которой следует пробел в начале строки. mangle_from_ по умолчанию соответствует значению параметра mangle_from_ policy (это True для политики compat32 и False для всех остальных). mangle_from_ предназначен для использования, когда сообщения хранятся в формате unix mbox (см. mailbox и ПОЧЕМУ ФОРМАТ CONTENT-LENGTH ПЛОХ).

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

Если указан policy, используйте эту политику для управления созданием сообщений. Если policy — это None (по умолчанию), используйте политику, связанную с объектом Message или EmailMessage, переданным в flatten, для управления созданием сообщения. См. email.policy для получения подробной информации о том, что контролирует 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 формат, путём преобразования их в совместимый с ASCII форматом Content- Transfer_Encoding. Используя терминологию RFC электронной почты, вы можете думать об этом как о сериализации Generator в поток ввода-вывода, который не является «8-битным чистым». Другими словами, большинство приложений захотят использовать BytesGenerator, а не Generator.

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

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

Если необязательный mangle_from_ равен True, помещает символ > перед любой начинающейся с точной строки "From " строкой в теле, т. е. From, за которой следует пробел в начале строки. mangle_from_ по умолчанию соответствует значению параметра mangle_from_ policy (это True для политики compat32 и False для всех остальных). mangle_from_ предназначен для использования, когда сообщения хранятся в формате unix mbox (см. mailbox и ПОЧЕМУ ФОРМАТ CONTENT-LENGTH ПЛОХ).

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

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

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

  • type – Полный MIME-тип части, отличной от text
  • maintype – основной MIME-тип части, отличной от text
  • subtype – Под-MIME-тип части, отличной от text
  • filename – Имя файла части, отличной от text
  • description – Описание, связанное с частью, отличной от text
  • encoding – Кодирование передачи содержимого части, отличной от text

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

«[Non-text (%(type)s) part of message omitted, filename %(filename)s]»

Дополнительные _mangle_from_ и maxheaderlen аналогичны базовому классу Generator.

Сноски

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