> **Источник:** https://python-all.ru/3.3/library/email.generator.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 19.1.3. [`email.generator`](https://python-all.ru/3.3/library/email.generator.html#module-email.generator): Создание MIME-документов

Одна из самых распространённых задач – сгенерировать плоский текст email-сообщения, представленного структурой объекта сообщения. Это понадобится, чтобы отправить сообщение через модуль [`smtplib`](https://python-all.ru/3.3/library/smtplib.html#module-smtplib) или модуль [`nntplib`](https://python-all.ru/3.3/library/nntplib.html#module-nntplib), либо вывести сообщение на консоль. Получение структуры объекта сообщения и создание плоского текстового документа – задача класса [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator).

Как и в случае с модулем [`email.parser`](https://python-all.ru/3.3/library/email.parser.html#module-email.parser), вы не ограничены функциональностью встроенного генератора; можно написать свой с нуля. Однако встроенный генератор умеет генерировать большинство email-сообщений в соответствии со стандартами, корректно обрабатывает MIME и не-MIME сообщения и спроектирован так, что преобразование из плоского текста в структуру сообщения через класс [`Parser`](https://python-all.ru/3.3/library/email.parser.html#email.parser.Parser) и обратно в плоский текст идемпотентно (вход идентичен выходу) [\[1\]](https://python-all.ru/3.3/library/email.generator.html#id3). С другой стороны, использование Generator на [`Message`](https://python-all.ru/3.3/library/email.message.html#email.message.Message), сконструированном программно, может привести к изменениям в объекте [`Message`](https://python-all.ru/3.3/library/email.message.html#email.message.Message), так как заполняются значения по умолчанию.

Вывод в [`bytes`](https://python-all.ru/3.3/library/functions.html#bytes) можно получить с помощью класса [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator). Если структура объекта сообщения содержит не-ASCII байты, метод [`flatten()`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator.flatten) этого генератора выдаст исходные байты. Разбор двоичного сообщения и последующее уплощение с помощью [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator) должно быть идемпотентным для сообщений, соответствующих стандартам.

Ниже перечислены публичные методы класса [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator), импортированные из модуля [`email.generator`](https://python-all.ru/3.3/library/email.generator.html#module-email.generator):

#### `class email.generator.Generator(outfp, mangle_from_=True, maxheaderlen=78, *, policy=None)`

Конструктор класса [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator) принимает аргумент – [*файлоподобный объект*](https://python-all.ru/3.3/glossary.html#term-file-like-object) с именем *outfp*. *outfp* должен поддерживать метод [`write()`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator.write) и быть пригодным для использования в качестве выходного файла для функции [`print()`](https://python-all.ru/3.3/library/functions.html#print).

Необязательный параметр *mangle\_from\_* – это флаг, который при значении `True` добавляет символ `>` перед любой строкой в теле, которая начинается точно как `From`, то есть `From`, за которым следует пробел в начале строки. Это единственный гарантированно переносимый способ избежать того, чтобы такие строки были приняты за разделитель заголовка конверта в формате почтового ящика Unix (см. [WHY THE CONTENT-LENGTH FORMAT IS BAD](https://python-all.ru/3.3/library/email.generator.html) для подробностей). *mangle\_from\_* по умолчанию равен `True`, но возможно, потребуется установить его в `False`, если вы не пишете файлы в формате почтового ящика Unix.

Необязательный параметр *maxheaderlen* задает максимальную длину для непродолженного заголовка. Если строка заголовка длиннее *maxheaderlen* (в символах, с табуляцией, развернутой в 8 пробелов), заголовок будет разбит, как определено в классе [`Header`](https://python-all.ru/3.3/library/email.header.html#email.header.Header). Установите значение 0, чтобы отключить перенос заголовков. По умолчанию 78, как рекомендовано (но не требуется) [**RFC 2822**](https://python-all.ru/3.3/library/email.generator.html).

Ключевое слово *policy* задает объект [`policy`](https://python-all.ru/3.3/library/email.policy.html#module-email.policy), управляющий рядом аспектов работы генератора. Если *policy* не указан, используется *policy*, прикрепленный к объекту сообщения, передаваемому в [`flatten`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator.flatten).

Изменено в версии 3.3: Добавлен параметр *policy*.

Другие публичные методы [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator):

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

Выводит текстовое представление структуры объекта сообщения, начиная с *msg*, в выходной файл, заданный при создании экземпляра [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator). Вложенные части обходятся в глубину, и результирующий текст будет корректно закодирован в MIME.

Необязательный параметр *unixfrom* – это флаг, который принудительно выводит разделитель заголовка конверта перед первым заголовком [**RFC 2822**](https://python-all.ru/3.3/library/email.generator.html) корневого объекта сообщения. Если у корневого объекта нет заголовка конверта, создается стандартный. По умолчанию установлено `False`, чтобы не выводить разделитель конверта.

Обратите внимание, что для вложенных частей заголовок конверта никогда не печатается.

Необязательный параметр *linesep* задает символ разделителя строк, используемый для завершения строк в выводе. Если указан, он переопределяет значение, заданное в *msg* или в `Generator` через `policy`.

Поскольку строки не могут представлять не-ASCII байты, если политика, действующая при вызове `flatten`, имеет [`cte_type`](https://python-all.ru/3.3/library/email.policy.html#email.policy.Policy.cte_type), установленный в `⟦/8bit`, то `Generator` будет работать так, как если бы он был установлен в `7bit`. Это означает, что сообщения, разобранные с помощью Bytes parser и имеющие *Content-Transfer-Encoding* равное `8bit`, будут преобразованы для использования `7bit` Content-Transfer-Encoding. Не-ASCII байты в заголовках будут [**RFC 2047**](https://python-all.ru/3.3/library/email.generator.html) закодированы с кодировкой `unknown-8bit`.

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

#### `clone(fp)`

Возвращает независимую копию этого экземпляра [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator) с точно такими же параметрами.

#### `write(s)`

Записывает строку *s* в базовый файловый объект, т.е. *outfp*, переданный конструктору [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator). Этого достаточно, чтобы экземпляры [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator) могли использоваться в функции [`print()`](https://python-all.ru/3.3/library/functions.html#print).

Для удобства см. методы [`Message`](https://python-all.ru/3.3/library/email.message.html#email.message.Message): [`as_string()`](https://python-all.ru/3.3/library/email.message.html#email.message.Message.as_string) и `str(aMessage)`, также известный как [`__str__()`](https://python-all.ru/3.3/library/email.message.html#email.message.Message.__str__), которые упрощают создание форматированного строкового представления объекта сообщения. Подробнее см. [`email.message`](https://python-all.ru/3.3/library/email.message.html#module-email.message).

#### `class email.generator.BytesGenerator(outfp, mangle_from_=True, maxheaderlen=78, *, policy=policy.default)`

Конструктор класса [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator) принимает аргумент – двоичный [*файлоподобный объект*](https://python-all.ru/3.3/glossary.html#term-file-like-object) с именем *outfp*. *outfp* должен поддерживать метод [`write()`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator.write), который принимает двоичные данные.

Необязательный параметр *mangle\_from\_* – это флаг, который при значении `True` добавляет символ `>` перед любой строкой в теле, которая начинается точно как `From`, то есть `From`, за которым следует пробел в начале строки. Это единственный гарантированно переносимый способ избежать того, чтобы такие строки были приняты за разделитель заголовка конверта в формате почтового ящика Unix (см. [WHY THE CONTENT-LENGTH FORMAT IS BAD](https://python-all.ru/3.3/library/email.generator.html) для подробностей). *mangle\_from\_* по умолчанию равен `True`, но возможно, потребуется установить его в `False`, если вы не пишете файлы в формате почтового ящика Unix.

Необязательный параметр *maxheaderlen* задает максимальную длину для непродолженного заголовка. Если строка заголовка длиннее *maxheaderlen* (в символах, с табуляцией, развернутой в 8 пробелов), заголовок будет разбит, как определено в классе [`Header`](https://python-all.ru/3.3/library/email.header.html#email.header.Header). Установите значение 0, чтобы отключить перенос заголовков. По умолчанию 78, как рекомендовано (но не требуется) [**RFC 2822**](https://python-all.ru/3.3/library/email.generator.html).

Параметр *policy* задаёт объект [`policy`](https://python-all.ru/3.3/library/email.policy.html#module-email.policy), который управляет рядом аспектов работы генератора. Политика по умолчанию обеспечивает обратную совместимость.

Изменено в версии 3.3: Добавлен параметр *policy*.

Другие публичные методы [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator):

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

Выводит текстовое представление структуры объекта сообщения, начиная с *msg*, в выходной файл, заданный при создании экземпляра [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator). Вложенные части обходятся в глубину, и результирующий текст будет корректно закодирован в MIME. Если опция [`policy`](https://python-all.ru/3.3/library/email.policy.html#module-email.policy) [`cte_type`](https://python-all.ru/3.3/library/email.policy.html#email.policy.Policy.cte_type) равна `8bit` (по умолчанию), то любые байты со старшим битом, установленным в исходном разобранном сообщении, которые не были изменены, будут скопированы в вывод без изменений. Если `cte_type` равно `7bit`, байты будут преобразованы по мере необходимости с использованием совместимой с ASCII Content-Transfer-Encoding. В частности, не-ASCII байты, недопустимые по RFC, в заголовках будут закодированы с использованием набора символов MIME `unknown-8bit`, что сделает их соответствующими RFC.

Сообщения, разобранные с помощью Bytes parser, которые имеют *Content-Transfer-Encoding* равный 8bit, будут восстановлены как 8bit, если они не были изменены.

Необязательный параметр *unixfrom* – это флаг, который принудительно выводит разделитель заголовка конверта перед первым заголовком [**RFC 2822**](https://python-all.ru/3.3/library/email.generator.html) корневого объекта сообщения. Если у корневого объекта нет заголовка конверта, создается стандартный. По умолчанию установлено `False`, чтобы не выводить разделитель конверта.

Обратите внимание, что для вложенных частей заголовок конверта никогда не печатается.

Необязательный параметр *linesep* задаёт символ разделителя строк, используемый для завершения строк в выводе. Если он указан, он переопределяет значение, заданное `Generator`‘s `policy`.

#### `clone(fp)`

Возвращает независимую копию этого экземпляра [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator) с теми же самыми параметрами.

#### `write(s)`

Write the string *s* to the underlying file object. *s* is encoded using the `ASCII` codec and written to the *write* method of the *outfp* *outfp* passed to the [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator)‘s constructor. This provides just enough file-like API for [`BytesGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.BytesGenerator) instances to be used in the [`print()`](https://python-all.ru/3.3/library/functions.html#print) function.

Новое в версии 3.2.

The [`email.generator`](https://python-all.ru/3.3/library/email.generator.html#module-email.generator) module also provides a derived class, called [`DecodedGenerator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.DecodedGenerator) which is like the [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator) base class, except that non-*text* parts are substituted with a format string representing the part.

#### `class email.generator.DecodedGenerator(outfp, mangle_from_=True, maxheaderlen=78, fmt=None)`

Этот класс, производный от [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator), обходит все подчасти сообщения. Если подчасть имеет основной тип *text*, то выводится декодированное содержимое подчасти. Необязательные параметры *\_mangle\_from\_* и *maxheaderlen* работают так же, как в базовом классе [`Generator`](https://python-all.ru/3.3/library/email.generator.html#email.generator.Generator).

Если подчасть не является основным типом *text*, необязательный параметр *fmt* – это форматная строка, используемая вместо содержимого сообщения. *fmt* разворачивается с использованием следующих ключевых слов в формате `%(keyword)s`:

- `type` – Full MIME type of the non-*text* part
- `maintype` – Main MIME type of the non-*text* part
- `subtype` – Sub-MIME type of the non-*text* part
- `filename` – Filename of the non-*text* part
- `description` – Description associated with the non-*text* part
- `encoding` – Content transfer encoding of the non-*text* part

Значение по умолчанию для *fmt* – `None`, что означает

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

Сноски

| [\[1\]](https://python-all.ru/3.3/library/email.generator.html#id1) | Это утверждение предполагает, что используется подходящая настройка для аргумента `unixfrom` и что установлено maxheaderlen=0 (что сохранит исходные длины строк). Кроме того, это не совсем верно, поскольку во многих случаях последовательности пробелов в заголовках схлопываются в одиночные пробелы. Последнее является ошибкой, которая в конечном итоге будет исправлена. |
| --- | --- |
