email.contentmanager.md
1> **Источник:** https://python-all.ru/3.5/library/email.contentmanager.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 19.1.6. [`email.contentmanager`](https://python-all.ru/3.5/library/email.contentmanager.html#module-email.contentmanager): Управление MIME-содержимым89Новое в версии 3.4: как [временный модуль](https://python-all.ru/3.5/glossary.html#term-provisional-package).1011**Исходный код:** [Lib/email/contentmanager.py](https://python-all.ru/src/3.5/Lib/email/contentmanager.py)1213> **Примечание**14>15> Модуль contentmanager был включен в стандартную библиотеку на [временной основе](https://python-all.ru/3.5/glossary.html#term-provisional-package). Обратно несовместимые изменения (вплоть до удаления модуля) могут быть внесены, если основные разработчики сочтут это необходимым.1617---1819Модуль [`message`](https://python-all.ru/3.5/library/email.message.html#module-email.message) предоставляет класс, который может представлять произвольное email-сообщение. Эта базовая модель сообщения имеет полезный и гибкий API, но предоставляет только низкоуровневый API для взаимодействия с общими частями сообщения (заголовки, общие параметры заголовков и полезная нагрузка, которая может быть списком подчастей). Этот модуль предоставляет классы и инструменты, которые обеспечивают расширенный и расширяемый API для работы с различными конкретными типами содержимого, включая возможность извлекать содержимое сообщения как объект специализированного типа, а не как простой объект байтов. Модуль автоматически обрабатывает RFC-специфичные MIME-детали (необходимые заголовки и параметры и т.д.) для определенных распространенных типов содержимого, а поддержка дополнительных типов может быть добавлена приложением с помощью механизмов расширения.2021Этот модуль определяет одноименные классы «Content Manager». Базовый класс [`ContentManager`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.ContentManager) определяет API для регистрации функций управления содержимым, которые извлекают данные из объектов `Message` или вставляют данные и заголовки в объекты `Message`, тем самым обеспечивая способ преобразования между объектами `Message`, содержащими данные, и другими представлениями этих данных (типы данных Python, специализированные объекты Python, внешние файлы и т.д.). Модуль также определяет один конкретный менеджер содержимого: [`raw_data_manager`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.raw_data_manager) преобразует между MIME-типами содержимого и данными `str` или `bytes`. Он также предоставляет удобный API для управления MIME-параметрами при вставке содержимого в `Message`. Также он обрабатывает вставку и извлечение объектов `Message` при работе с типом содержимого `message/rfc822`.2223Еще одна часть расширенного интерфейса – подклассы [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message), которые предоставляют новые удобные функции API, включая удобные методы для вызова менеджеров содержимого, производных от этого модуля.2425> **Примечание**26>27> Хотя [`EmailMessage`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage) и [`MIMEPart`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.MIMEPart) в настоящее время документированы в этом модуле из-за временного характера кода, реализация находится в модуле [`email.message`](https://python-all.ru/3.5/library/email.message.html#module-email.message).2829#### `class email.message.EmailMessage(policy=default)`3031Если указан *policy* (он должен быть экземпляром класса [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy)), используйте указанные им правила для обновления и сериализации представления сообщения. Если *policy* не задан, используйте политику [`default`](https://python-all.ru/3.5/library/email.policy.html#email.policy.default), которая следует правилам email RFC, за исключением окончаний строк (вместо требуемого RFC `\r\n` используется стандартное для Python `\n` окончание строк). Дополнительную информацию см. в документации [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy).3233Этот класс является подклассом [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message). Он добавляет следующие методы:3435#### `is_attachment()`3637Возвращает `True`, если присутствует заголовок *Content-Disposition* и его значение (без учёта регистра) равно `attachment`, иначе `False`.3839Изменено в версии 3.4.2: is\_attachment теперь метод, а не свойство, для согласованности с [`is_multipart()`](https://python-all.ru/3.5/library/email.message.html#email.message.Message.is_multipart).4041#### `get_body(preferencelist=('related', 'html', 'plain'))`4243Возвращает MIME-часть, которая наилучшим образом подходит на роль «тела» сообщения.4445*preferencelist* должен быть последовательностью строк из набора `related`, `html` и `plain` и указывает порядок предпочтения типа содержимого возвращаемой части.4647Поиск подходящих кандидатов начинается с объекта, для которого вызван метод `get_body`.4849Если `related` не включён в *preferencelist*, корневая часть (или подчасть корневой части) любой встреченной связанной части рассматривается как кандидат, если эта (под)часть соответствует предпочтению.5051При обнаружении `multipart/related` проверяется параметр `start`, и если найдена часть с соответствующим *Content-ID*, то при поиске подходящих кандидатов рассматривается только она. В противном случае рассматривается только первая (корневая по умолчанию) часть `multipart/related`.5253Если часть имеет заголовок *Content-Disposition*, то часть считается подходящим кандидатом только если значение заголовка равно `inline`.5455Если ни один из кандидатов не соответствует ни одному предпочтению из *preferencelist*, возвращается `None`.5657Примечания: (1) Для большинства приложений единственные комбинации *preferencelist*, которые действительно имеют смысл: `('plain',)`, `('html', 'plain')` и значение по умолчанию `('related', 'html', 'plain')`. (2) Поскольку сопоставление начинается с объекта, для которого вызывается `get_body`, вызов `get_body` на `multipart/related` вернет сам объект, если только *preferencelist* не имеет нестандартного значения. (3) Сообщения (или части сообщений), которые не указывают *Content-Type* или чей заголовок *Content-Type* недействителен, будут обрабатываться как имеющие тип `text/plain`, что иногда может приводить к неожиданным результатам `get_body`.5859#### `iter_attachments()`6061Возвращает итератор по всем частям сообщения, которые не являются кандидатами на «тело». То есть пропускает первое вхождение каждого из `text/plain`, `text/html`, `multipart/related` или `multipart/alternative` (если только они явно не помечены как вложения через *Content-Disposition: attachment*) и возвращает все остальные части. При непосредственном применении к `multipart/related` возвращает итератор по всем связанным частям, кроме корневой (т.е. части, на которую указывает параметр `start`, или первой части, если параметр `start` отсутствует или параметр `start` не соответствует *Content-ID* ни одной из частей). При непосредственном применении к `multipart/alternative` или не-`multipart` возвращает пустой итератор.6263#### `iter_parts()`6465Возвращает итератор по всем непосредственным подчастям сообщения; для не-`multipart` итератор будет пустым. (См. также `walk()`.)6667#### `get_content(*args, content_manager=None, **kw)`6869Вызывает метод `get_content` объекта *content\_manager*, передавая self в качестве объекта сообщения и передавая любые другие аргументы или ключевые слова как дополнительные аргументы. Если *content\_manager* не указан, используется `content_manager`, заданный текущим [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy).7071#### `set_content(*args, content_manager=None, **kw)`7273Вызывает метод `set_content` объекта *content\_manager*, передавая self в качестве объекта сообщения и передавая любые другие аргументы или ключевые слова как дополнительные аргументы. Если *content\_manager* не указан, используется `content_manager`, заданный текущим [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy).7475#### `make_related(boundary=None)`7677Преобразует сообщение, не являющееся `multipart`, в сообщение `multipart/related`, перемещая все существующие заголовки *Content-* и полезную нагрузку в (новую) первую часть `multipart`. Если указан *boundary*, он используется в качестве строки границы в multipart, в противном случае граница будет создана автоматически при необходимости (например, при сериализации сообщения).7879#### `make_alternative(boundary=None)`8081Преобразует сообщение, не являющееся `multipart` или являющееся `multipart/related`, в сообщение `multipart/alternative`, перемещая все существующие заголовки *Content-* и полезную нагрузку в (новую) первую часть `multipart`. Если указан *boundary*, он используется в качестве строки границы в multipart, в противном случае граница будет создана автоматически при необходимости (например, при сериализации сообщения).8283#### `make_mixed(boundary=None)`8485Преобразует сообщение, не являющееся `multipart`, являющееся `multipart/related` или `multipart-alternative`, в сообщение `multipart/mixed`, перемещая все существующие заголовки *Content-* и полезную нагрузку в (новую) первую часть `multipart`. Если указан *boundary*, он используется в качестве строки границы в multipart, в противном случае граница будет создана автоматически при необходимости (например, при сериализации сообщения).8687#### `add_related(*args, content_manager=None, **kw)`8889Если сообщение является `multipart/related`, создаётся новый объект сообщения, все аргументы передаются его методу [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.set_content), и [`attach()`](https://python-all.ru/3.5/library/email.message.html#email.message.Message.attach) его к `multipart`. Если сообщение не является `multipart`, вызывается [`make_related()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.make_related), после чего выполняется описанное выше. Если сообщение относится к любому другому типу `multipart`, возбуждается [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError). Если *content\_manager* не указан, используется `content_manager`, заданный текущим [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy). Если у добавленной части нет заголовка *Content-Disposition*, добавляется заголовок со значением `inline`.9091#### `add_alternative(*args, content_manager=None, **kw)`9293Если сообщение является `multipart/alternative`, создаётся новый объект сообщения, все аргументы передаются его методу [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.set_content), и [`attach()`](https://python-all.ru/3.5/library/email.message.html#email.message.Message.attach) его к `multipart`. Если сообщение не является `multipart` или является `multipart/related`, вызывается [`make_alternative()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.make_alternative), после чего выполняется описанное выше. Если сообщение относится к любому другому типу `multipart`, возбуждается [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError). Если *content\_manager* не указан, используется `content_manager`, заданный текущим [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy).9495#### `add_attachment(*args, content_manager=None, **kw)`9697Если сообщение является `multipart/mixed`, создайте новый объект сообщения, передайте все аргументы его методу [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.set_content) и [`attach()`](https://python-all.ru/3.5/library/email.message.html#email.message.Message.attach) его в `multipart`. Если сообщение является не-`multipart`, `multipart/related` или `multipart/alternative`, вызовите [`make_mixed()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.make_mixed) и затем действуйте как выше. Если *content\_manager* не указан, используйте `content_manager`, заданный текущим [`policy`](https://python-all.ru/3.5/library/email.policy.html#module-email.policy). Если добавленная часть не имеет заголовка *Content-Disposition*, добавьте заголовок со значением `attachment`. Этот метод можно использовать как для явных вложений (*Content-Disposition: attachment*, так и для `inline` вложений (*Content-Disposition: inline*) путем передачи соответствующих параметров в `content_manager`.9899#### `clear()`100101Удаляет полезную нагрузку и все заголовки.102103#### `clear_content()`104105Удаляет полезную нагрузку и все заголовки `Content-`, оставляя все остальные заголовки нетронутыми и в исходном порядке.106107#### `class email.message.MIMEPart(policy=default)`108109Этот класс представляет подчасть MIME-сообщения. Он идентичен [`EmailMessage`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage), за исключением того, что заголовки *MIME-Version* не добавляются при вызове [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.set_content), поскольку подчасти не нуждаются в собственных заголовках *MIME-Version*.110111#### `class email.contentmanager.ContentManager`112113Базовый класс для диспетчеров содержимого. Предоставляет стандартные механизмы регистрации для преобразователей между MIME-содержимым и другими представлениями, а также методы отправки `get_content` и `set_content`.114115#### `get_content(msg, *args, **kw)`116117Находит функцию-обработчик на основе `mimetype` сообщения *msg* (см. следующий абзац), вызывает её, передавая все аргументы, и возвращает результат вызова. Ожидается, что обработчик извлечёт полезную нагрузку из *msg* и вернёт объект, который кодирует информацию об извлечённых данных.118119Для поиска обработчика ищутся следующие ключи в реестре; поиск прекращается при первом найденном:120121> - строка, представляющая полный MIME-тип (`maintype/subtype`)122> - строка, представляющая `maintype`123> - пустая строка124125Если ни один из этих ключей не дал обработчика, возбуждается [`KeyError`](https://python-all.ru/3.5/library/exceptions.html#KeyError) для полного MIME-типа.126127#### `set_content(msg, obj, *args, **kw)`128129Если `maintype` равно `multipart`, возбуждается [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError); в противном случае находится функция-обработчик на основе типа *obj* (см. следующий абзац), вызывается [`clear_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage.clear_content) на *msg* и вызывается функция-обработчик с передачей всех аргументов. Ожидается, что обработчик преобразует и сохранит *obj* в *msg*, возможно, внося также другие изменения в *msg*, например, добавляя различные MIME-заголовки для кодирования информации, необходимой для интерпретации сохранённых данных.130131Для поиска обработчика получается тип *obj* (`typ = type(obj)`), и в реестре ищутся следующие ключи; поиск прекращается при первом найденном:132133> - сам тип (`typ`)134> - полное квалифицированное имя типа (`typ.__module__ + '.' + typ.__qualname__`).135> - qualname типа (`typ.__qualname__`)136> - имя типа (`typ.__name__`).137138Если ни одно из вышеперечисленных не совпадает, повторить все проверки выше для каждого из типов в [MRO](https://python-all.ru/3.5/glossary.html#term-mro) (`typ.__mro__`). Наконец, если ни один другой ключ не даёт обработчика, проверить наличие обработчика для ключа `None`. Если обработчика для `None` нет, вызвать [`KeyError`](https://python-all.ru/3.5/library/exceptions.html#KeyError) для полного имени типа.139140Также добавляется заголовок *MIME-Version*, если он отсутствует (см. также [`MIMEPart`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.MIMEPart)).141142#### `add_get_handler(key, handler)`143144Регистрирует функцию *handler* как обработчик для *key*. Возможные значения *key* описаны в [`get_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.get_content).145146#### `add_set_handler(typekey, handler)`147148Регистрирует *handler* как функцию, вызываемую, когда объект типа, соответствующего *typekey*, передаётся в [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.set_content). Возможные значения *typekey* описаны в [`set_content()`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.set_content).149150## 19.1.6.1. Экземпляры Content Manager151152В настоящее время пакет email предоставляет только один конкретный диспетчер содержимого – [`raw_data_manager`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.raw_data_manager), хотя в будущем может быть добавлено больше. [`raw_data_manager`](https://python-all.ru/3.5/library/email.contentmanager.html#email.contentmanager.raw_data_manager) – это [`content_manager`](https://python-all.ru/3.5/library/email.policy.html#email.policy.EmailPolicy.content_manager), предоставляемый [`EmailPolicy`](https://python-all.ru/3.5/library/email.policy.html#email.policy.EmailPolicy) и его производными.153154#### `email.contentmanager.raw_data_manager`155156Этот диспетчер содержимого предоставляет лишь минимальный интерфейс в дополнение к тому, что предоставляет сам [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message): он работает только с текстом, необработанными байтовыми строками и объектами [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message). Тем не менее, он даёт значительные преимущества по сравнению с базовым API: `get_content` для текстовой части возвращает строку Unicode без необходимости ручного декодирования, `set_content` предоставляет богатый набор опций для управления заголовками, добавляемыми к части, и управления кодировкой передачи содержимого, а также позволяет использовать различные методы `add_`, упрощая создание многокомпонентных сообщений.157158#### `email.contentmanager.get_content(msg, errors='replace')`159160Возвращает содержимое части как строку (для частей `text`), объект [`EmailMessage`](https://python-all.ru/3.5/library/email.contentmanager.html#email.message.EmailMessage) (для частей `message/rfc822`) или объект `bytes` (для всех других не multipart-типов). Вызывает [`KeyError`](https://python-all.ru/3.5/library/exceptions.html#KeyError) при вызове для `multipart`. Если часть является `text` и указан *errors*, использует его как обработчик ошибок при декодировании содержимого в unicode. Обработчик ошибок по умолчанию – `replace`.161162#### `email.contentmanager.set_content(msg, <'str'>, subtype="plain", charset='utf-8' cte=None, disposition=None, filename=None, cid=None, params=None, headers=None)`163164#### `email.contentmanager.set_content(msg, <'bytes'>, maintype, subtype, cte="base64", disposition=None, filename=None, cid=None, params=None, headers=None)`165166#### `email.contentmanager.set_content(msg, <'Message'>, cte=None, disposition=None, filename=None, cid=None, params=None, headers=None)`167168#### `email.contentmanager.set_content(msg, <'list'>, subtype='mixed', disposition=None, filename=None, cid=None, params=None, headers=None)`169170Добавляет заголовки и содержимое в *msg*:171172Добавляет заголовок *Content-Type* со значением `maintype/subtype`.173174> - Для `str` устанавливает MIME `maintype` в `text`, а подтип – в *subtype*, если он указан, или в `plain`, если нет.175> - Для `bytes` использует указанные *maintype* и *subtype*, или вызывает [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError), если они не указаны.176> - Для объектов [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message) установите maintype в `message`, а subtype – в *subtype*, если он указан, или в `rfc822`, если нет. Если *subtype* равен `partial`, вызовите исключение (объекты `bytes` должны использоваться для создания частей `message/partial`).177> - Для *\<’list’\>*, который должен быть списком объектов [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message), установите `maintype` в `multipart`, а `subtype` – в *subtype*, если он указан, и в `mixed`, если нет. Если части сообщения в *\<’list’\>* имеют заголовки *MIME-Version*, удалите их.178179Если указан *charset* (действителен только для `str`), кодирует строку в байты с использованием указанной кодировки. По умолчанию используется `utf-8`. Если указанный *charset* является известным псевдонимом стандартного имени кодировки MIME, использует стандартную кодировку.180181Если *cte* установлен, закодируйте полезную нагрузку с помощью указанного кодирования передачи содержимого и установите заголовок *Content-Transfer-Encoding* в это значение. Для объектов `str`, если он не установлен, используйте эвристику для определения наиболее компактного кодирования. Возможные значения для *cte*: `quoted-printable`, `base64`, `7bit`, `8bit` и `binary`. Если входные данные невозможно закодировать с помощью указанного кодирования (например, `7bit`), вызовите [`ValueError`](https://python-all.ru/3.5/library/exceptions.html#ValueError). Для [`Message`](https://python-all.ru/3.5/library/email.message.html#email.message.Message), согласно [**RFC 2046**](https://python-all.ru/3.5/library/email.contentmanager.html), вызовите исключение, если для *subtype* `rfc822` запрошен *cte* равный `quoted-printable` или `base64`, и для любого *cte* отличного от `7bit` для *subtype* `external-body`. Для `message/rfc822` используйте `8bit`, если *cte* не указан. Для всех остальных значений *subtype* используйте `7bit`.182183> **Примечание**184>185> *cte* равный `binary` пока работает некорректно. Объект `Message`, изменённый с помощью `set_content`, правилен, но [`BytesGenerator`](https://python-all.ru/3.5/library/email.generator.html#email.generator.BytesGenerator) не сериализует его корректно.186187Если *disposition* установлен, используйте его как значение заголовка *Content-Disposition*. Если не указан, а *filename* указан, добавьте заголовок со значением `attachment`. Если он не указан и *filename* тоже не указан, не добавляйте заголовок. Единственные допустимые значения для *disposition*: `attachment` и `inline`.188189Если *filename* указан, используйте его как значение параметра `filename` заголовка *Content-Disposition*. Значения по умолчанию нет.190191Если указан *cid*, добавляет заголовок *Content-ID* со значением *cid*.192193Если указан *params*, перебирает его метод `items` и использует полученные пары `(key, value)` для установки дополнительных параметров заголовка *Content-Type*.194195Если указан *headers* и это список строк вида `headername: headervalue` или список объектов `header` (отличаются от строк наличием атрибута `name`), добавляет заголовки в *msg*.196