email.message: Representing an email message

Вихідний код: Lib/email/message.py


Added in version 3.6: [1]

Центральним класом у пакеті email є клас EmailMessage, імпортований із модуля email.message. Це базовий клас для об’єктної моделі email. EmailMessage забезпечує основну функціональність для налаштування та запиту полів заголовків, для доступу до тіла повідомлень, а також для створення або зміни структурованих повідомлень.

Повідомлення електронної пошти складається з заголовків і корисного навантаження (яке також називають контентом). Заголовки — це імена та значення полів у стилі RFC 5322 або RFC 6532, де назва поля та значення розділені двокрапкою. Двокрапка не є частиною ані імені поля, ані значення поля. Корисне навантаження може бути простим текстовим повідомленням, або двійковим об’єктом, або структурованою послідовністю підповідомлень, кожне з яких має власний набір заголовків і власне корисне навантаження. Останній тип корисного навантаження вказується повідомленням, що має тип MIME, наприклад multipart/* або message/rfc822.

Концептуальна модель, надана об’єктом EmailMessage, — це впорядкований словник заголовків у поєднанні з корисним навантаженням, який представляє тіло RFC 5322 повідомлення, яке може бути списком під-` Об’єкти EmailMessage. На додаток до звичайних методів словника для доступу до імен і значень заголовків, існують методи для доступу до спеціальної інформації із заголовків (наприклад, типу вмісту MIME), для роботи з корисним навантаженням, для генерації серіалізованої версії повідомлення та для рекурсивного переходу по дереву об’єктів.

The EmailMessage dictionary-like interface is indexed by the header names, which must be ASCII values. The values of the dictionary are strings with some extra methods. Headers are stored and returned in case-preserving form, but field names are matched case-insensitively. The keys are ordered, but unlike a real dict, there can be duplicates. Additional methods are provided for working with headers that have duplicate keys.

Корисне навантаження — це об’єкт рядка чи байтів у випадку простих об’єктів повідомлення, або список об’єктів EmailMessage для документів-контейнерів MIME, таких як multipart/* і message/rfc822 об’єкти повідомлення.

class email.message.EmailMessage(policy=default)

Якщо вказано політику, використовуйте правила, які вона визначає, щоб оновити та серіалізувати представлення повідомлення. Якщо policy не встановлено, використовуйте політику default, яка відповідає правилам RFC електронної пошти, за винятком закінчення рядків (замість RFC, передбаченого \r\n, він використовує стандартні закінчення рядків Python \n). Для отримання додаткової інформації дивіться документацію policy.

as_string(unixfrom=False, maxheaderlen=None, policy=None)

Return the entire message flattened as a string. When optional unixfrom is true, the envelope header is included in the returned string. unixfrom defaults to False. For backward compatibility with the base Message class maxheaderlen is accepted, but defaults to None, which means that by default the line length is controlled by the max_line_length of the policy. The policy argument may be used to override the default policy obtained from the message instance. This can be used to control some of the formatting produced by the method, since the specified policy will be passed to the Generator.

Зведення повідомлення може викликати зміни в EmailMessage, якщо для завершення перетворення в рядок необхідно вказати значення за умовчанням (наприклад, можуть бути згенеровані або змінені межі MIME).

Зауважте, що цей метод надається для зручності та може бути не найкориснішим способом серіалізації повідомлень у вашій програмі, особливо якщо ви маєте справу з кількома повідомленнями. Перегляньте email.generator.Generator для більш гнучкого API для серіалізації повідомлень. Зауважте також, що цей метод обмежений створенням повідомлень, серіалізованих як «7 bit clean», якщо utf8 має значення False, що є типовим.

Змінено в версії 3.6: поведінку за замовчуванням, коли maxheaderlen не вказано, було змінено з 0 на значення max_line_length із політики.

__str__()

Еквівалент as_string(policy=self.policy.clone(utf8=True)). Дозволяє str(msg) створювати рядок, що містить серіалізоване повідомлення в читабельному форматі.

Змінено в версії 3.4: метод було змінено на використання utf8=True, таким чином створюючи представлення повідомлення, схоже на RFC 6531, замість прямого псевдоніма для as_string().

as_bytes(unixfrom=False, policy=None)

Повертає все повідомлення зведене як об’єкт bytes. Якщо необов’язковий параметр unixfrom має значення true, заголовок конверта включається до поверненого рядка. unixfrom за умовчанням має значення False. Аргумент policy можна використовувати для заміни політики за замовчуванням, отриманої з екземпляра повідомлення. Це можна використовувати для керування частиною форматування, створеного методом, оскільки вказану політику буде передано до BytesGenerator.

Зведення повідомлення може викликати зміни в EmailMessage, якщо для завершення перетворення в рядок необхідно вказати значення за умовчанням (наприклад, можуть бути згенеровані або змінені межі MIME).

Зауважте, що цей метод надається для зручності та може бути не найкориснішим способом серіалізації повідомлень у вашій програмі, особливо якщо ви маєте справу з кількома повідомленнями. Перегляньте email.generator.BytesGenerator для більш гнучкого API для серіалізації повідомлень.

__bytes__()

Equivalent to as_bytes(). Allows bytes(msg) to produce a bytes object containing the serialized message.

is_multipart()

Повертає True, якщо корисним навантаженням повідомлення є список sub-EmailMessage об’єктів, інакше повертає False. Коли is_multipart() повертає False, корисним навантаженням має бути рядковий об’єкт (який може бути двійковим навантаженням у кодуванні CTE). Зауважте, що is_multipart(), що повертає True, не обов’язково означає, що «msg.get_content_maintype() == „multipart“» поверне True. Наприклад, is_multipart поверне True, якщо EmailMessage має тип message/rfc822.

set_unixfrom(unixfrom)

Встановіть заголовок конверта повідомлення на unixfrom, який має бути рядком. (Див. mboxMessage для короткого опису цього заголовка.)

get_unixfrom()

Повернути заголовок конверта повідомлення. За замовчуванням None, якщо заголовок конверта ніколи не встановлювався.

Наступні методи реалізують схожий на відображення інтерфейс для доступу до заголовків повідомлення. Зверніть увагу, що існують деякі семантичні відмінності між цими методами та інтерфейсом звичайного відображення (тобто словника). Наприклад, у словнику немає дублікатів ключів, але тут можуть бути дублікати заголовків повідомлень. Крім того, у словниках немає гарантованого порядку ключів, які повертає keys(), але в об’єкті EmailMessage заголовки завжди повертаються в тому порядку, в якому вони з’явилися в оригінальному повідомленні або в якому вони були додані до повідомлення пізніше. Будь-який заголовок, видалений і потім знову доданий, завжди додається в кінець списку заголовків.

Ці семантичні відмінності є навмисними та спрямовані на зручність у найпоширеніших випадках використання.

Зауважте, що в усіх випадках будь-який заголовок конверта, присутній у повідомленні, не включається в інтерфейс зіставлення.

__len__()

Повертає загальну кількість заголовків, включаючи дублікати.

__contains__(name)

Повертає True, якщо об’єкт повідомлення має поле з назвою name. Зіставлення виконується без урахування регістру, а ім’я не містить двокрапки в кінці. Використовується для оператора in. Наприклад:

if 'message-id' in myMessage:
   print('Message-ID:', myMessage['message-id'])
__getitem__(name)

Повертає значення названого поля заголовка. ім’я не містить двокрапку-роздільник полів. Якщо заголовок відсутній, повертається None; a KeyError ніколи не виникає.

Зауважте, що якщо назване поле з’являється більше одного разу в заголовках повідомлення, яке саме значення полів буде повернуто, не визначено. Використовуйте метод get_all(), щоб отримати значення всіх існуючих заголовків з назвою name.

Використовуючи стандартні політики (не compat32), повернуте значення є екземпляром підкласу email.headerregistry.BaseHeader.

__setitem__(name, val)

Додайте до повідомлення заголовок із назвою поля name і значенням val. Поле додається в кінці існуючих заголовків повідомлення.

Зауважте, що це не перезаписує та не видаляє будь-який існуючий заголовок із такою ж назвою. Якщо ви хочете переконатися, що новий заголовок є єдиним у повідомленні з назвою поля name, спочатку видаліть це поле, наприклад:

del msg['subject']
msg['subject'] = 'Python roolz!'

If the policy defines certain headers to be unique (as the standard policies do), this method may raise a ValueError when an attempt is made to assign a value to such a header when one already exists. This behavior is intentional for consistency’s sake, but do not depend on it as we may choose to make such assignments do an automatic deletion of the existing header in the future.

__delitem__(name)

Видалити всі входження поля з назвою ім’я із заголовків повідомлення. Жодного винятку не створюється, якщо назване поле відсутнє в заголовках.

keys()

Повертає список імен усіх полів заголовка повідомлення.

values()

Повертає список усіх значень полів повідомлення.

items()

Повертає список із двох кортежів, що містить усі заголовки та значення полів повідомлення.

get(name, failobj=None)

Return the value of the named header field. This is identical to __getitem__() except that optional failobj is returned if the named header is missing (failobj defaults to None).

Ось кілька додаткових корисних методів, пов’язаних із заголовками:

get_all(name, failobj=None)

Повертає список усіх значень для поля з назвою name. Якщо в повідомленні немає таких іменованих заголовків, повертається failobj (за замовчуванням None).

add_header(_name, _value, **_params)

Розширене налаштування заголовка. Цей метод подібний до __setitem__() за винятком того, що додаткові параметри заголовка можуть бути надані як аргументи ключового слова. _name — це поле заголовка, яке потрібно додати, а _value — це основне значення для заголовка.

Для кожного елемента в словнику аргументів ключових слів _params ключ береться як ім’я параметра, а символи підкреслення перетворюються на тире (оскільки тире заборонені в ідентифікаторах Python). Зазвичай параметр буде додано як key="value", якщо значення не буде None, у цьому випадку буде додано лише ключ.

Якщо значення містить символи, відмінні від ASCII, кодуванням і мовою можна явно керувати, вказавши значення у вигляді трьох кортежів у форматі (НАБОР СИГНАЛІВ, МОВА, ЗНАЧЕННЯ), де НАБІР СИГНАЛІВ — це назва рядка набір символів, який буде використано для кодування значення, LANGUAGE зазвичай може бути встановлено на None або порожній рядок (перегляньте RFC 2231 для інших можливостей), а VALUE є значення рядка, що містить кодові точки, відмінні від ASCII. Якщо три кортежу не передано і значення містить символи, відмінні від ASCII, воно автоматично кодується у форматі RFC 2231 з використанням CHARSET utf-8 і LANGUAGE з Жодного.

Ось приклад:

msg.add_header('Content-Disposition', 'attachment', filename='bud.gif')

Це додасть заголовок, який виглядає так:

Content-Disposition: attachment; filename="bud.gif"

Приклад розширеного інтерфейсу з не-ASCII символами:

msg.add_header('Content-Disposition', 'attachment',
               filename=('iso-8859-1', '', 'Fußballer.ppt'))
replace_header(_name, _value)

Замінити заголовок. Замініть перший знайдений у повідомленні заголовок, який відповідає _name, зберігаючи порядок заголовків і регістр імені поля вихідного заголовка. Якщо відповідного заголовка не знайдено, викликайте KeyError.

get_content_type()

Повертає тип вмісту повідомлення, переведений у нижній регістр у формі maintype/subtype. Якщо в повідомленні немає заголовка Content-Type, повертається значення, яке повертає get_default_type(). Якщо заголовок Content-Type недійсний, поверніть text/plain.

(Відповідно до RFC 2045, повідомлення завжди мають тип за замовчуванням, get_content_type() завжди повертатиме значення. RFC 2045 визначає тип повідомлення за замовчуванням як text/plain якщо він не з’являється всередині контейнера multipart/digest, у такому випадку це буде message/rfc822. Якщо заголовок Content-Type має недійсну специфікацію типу, RFC 2045 вимагає, щоб тип за замовчуванням був text/plain.)

get_content_maintype()

Повернути основний тип вмісту повідомлення. Це maintype частина рядка, яку повертає get_content_type().

get_content_subtype()

Повернути тип підвмісту повідомлення. Це subtype частина рядка, яку повертає get_content_type().

get_default_type()

Повернути типовий тип вмісту. Більшість повідомлень мають стандартний тип вмісту text/plain, за винятком повідомлень, які є підчастинами контейнерів multipart/digest. Такі підчастини мають типовий тип вмісту message/rfc822.

set_default_type(ctype)

Встановіть тип вмісту за замовчуванням. ctype має бути text/plain або message/rfc822, хоча це не обов’язково. Тип вмісту за замовчуванням не зберігається в заголовку Content-Type, тому він впливає лише на значення, що повертається методами get_content_type, якщо в повідомленні немає заголовка Content-Type .

set_param(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)

Установіть параметр у заголовку Content-Type. Якщо параметр уже існує в заголовку, замініть його значення на value. Якщо header має значення Content-Type (за замовчуванням), а заголовок ще не існує в повідомленні, додайте його, установіть для нього значення text/plain і додайте нове значення параметра. Необов’язковий header визначає альтернативний заголовок Content-Type.

Якщо значення містить символи, відмінні від ASCII, кодування та мову можна вказати явно за допомогою додаткових параметрів charset і language. Необов’язковий мова вказує мову RFC 2231, за умовчанням порожній рядок. І charset, і language мають бути рядками. За замовчуванням для мови використовується utf8 charset і None.

Якщо replace має значення False (за замовчуванням), заголовок переміщується в кінець списку заголовків. Якщо replace має значення True, заголовок буде оновлено на місці.

Використання параметра requote з об’єктами EmailMessage застаріло.

Note that existing parameter values of headers may be accessed through the params attribute of the header value (for example, msg['Content-Type'].params['charset']).

Змінено в версії 3.4: Додано ключове слово replace.

del_param(param, header='content-type', requote=True)

Повністю вилучіть вказаний параметр із заголовка Content-Type. Заголовок буде перезаписано на місці без параметра чи його значення. Необов’язковий заголовок визначає альтернативу Content-Type.

Використання параметра requote з об’єктами EmailMessage застаріло.

get_filename(failobj=None)

Повертає значення параметра filename заголовка Content-Disposition повідомлення. Якщо заголовок не має параметра filename, цей метод повертається до пошуку параметра name у заголовку Content-Type. Якщо нічого не знайдено або відсутній заголовок, повертається failobj. Повернений рядок завжди буде без лапок відповідно до email.utils.unquote().

get_boundary(failobj=None)

Повертає значення параметра boundary заголовка Content-Type повідомлення або failobj, якщо заголовок відсутній або не має параметра boundary. Повернений рядок завжди буде без лапок відповідно до email.utils.unquote().

set_boundary(boundary)

Установіть для параметра boundary заголовка Content-Type значення boundary. set_boundary() завжди братиме boundary у лапки, якщо необхідно. Помилка HeaderParseError виникає, якщо об’єкт повідомлення не має заголовка Content-Type.

Зауважте, що використання цього методу дещо відрізняється від видалення старого заголовка Content-Type і додавання нового з новою межею за допомогою add_header(), оскільки set_boundary() зберігає порядок заголовок Content-Type у списку заголовків.

get_content_charset(failobj=None)

Повертає параметр charset заголовка Content-Type у нижньому регістрі. Якщо немає заголовка Content-Type або цей заголовок не має параметра charset, повертається failobj.

get_charsets(failobj=None)

Повернути список із назвами наборів символів у повідомленні. Якщо повідомлення є multipart, тоді список міститиме один елемент для кожної підчастини в корисному навантаженні, інакше це буде список довжиною 1.

Кожен елемент у списку буде рядком, який є значенням параметра charset у заголовку Content-Type для представленої підчастини. Якщо підчастина не має заголовка Content-Type, параметра charset або не належить до основного типу MIME text, тоді цей елемент у списку буде failobj .

is_attachment()

Повертає True, якщо є заголовок Content-Disposition і його (незалежне від регістру) значення є attachment, False інакше.

Змінено в версії 3.4.2: is_attachment тепер є методом замість властивості, для узгодженості з is_multipart().

get_content_disposition()

Повертає значення в нижньому регістрі (без параметрів) заголовка повідомлення Content-Disposition, якщо воно є, або None. Можливі значення для цього методу: inline, attachment або None, якщо повідомлення слідує за RFC 2183.

Added in version 3.5.

Наступні методи стосуються опитування та маніпулювання вмістом (корисним навантаженням) повідомлення.

walk()

Метод walk() — це універсальний генератор, який можна використовувати для перебору всіх частин і підчастин дерева об’єктів повідомлення в порядку проходження спочатку в глибину. Ви зазвичай використовуєте walk() як ітератор у циклі for; кожна ітерація повертає наступну підчастину.

Ось приклад, який друкує тип MIME кожної частини структури повідомлення, що складається з кількох частин:

>>> for part in msg.walk():
...     print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
text/plain

walk повторює підчастини будь-якої частини, де is_multipart() повертає True, навіть якщо msg.get_content_maintype() == 'multipart' може повернути False. Ми можемо побачити це в нашому прикладі, використовуючи допоміжну функцію налагодження _structure:

>>> from email.iterators import _structure
>>> for part in msg.walk():
...     print(part.get_content_maintype() == 'multipart',
...           part.is_multipart())
True True
False False
False True
False False
False False
False True
False False
>>> _structure(msg)
multipart/report
    text/plain
    message/delivery-status
        text/plain
        text/plain
    message/rfc822
        text/plain

Тут частини message не є multiparts, але вони містять підчастини. is_multipart() повертає True і walk спускається до підчастин.

get_body(preferencelist=('related', 'html', 'plain'))

Повертає частину MIME, яка є найкращим кандидатом на роль «тіла» повідомлення.

preferencelist має бути послідовністю рядків із набору related, html і plain і вказує на порядок пріоритету для типу вмісту повернутої частини.

Почніть шукати збіги кандидатів з об’єктом, для якого викликається метод get_body.

Якщо related не включено до preferencelist, розгляньте кореневу частину (або підчастину кореневої частини) будь-якої пов’язаної частини як кандидата, якщо (під)частина відповідає налаштуванню.

Коли ви зустрічаєте multipart/related, перевірте параметр start, і якщо знайдено частину з відповідним Content-ID, враховуйте лише його під час пошуку збігів кандидатів. В іншому випадку враховуйте лише першу (за замовчуванням кореневу) частину multipart/related.

Якщо частина має заголовок Content-Disposition, розглядайте цю частину як кандидат-збіг, лише якщо значення заголовка є inline.

Якщо жоден із кандидатів не відповідає жодному з параметрів у preferencelist, поверніть None.

Примітки: (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 може повертати несподівані результати.

iter_attachments()

Повертає ітератор над усіма безпосередніми підчастинами повідомлення, які не є кандидатами на «тіло». Тобто пропустіть перше входження кожного з text/plain, text/html, multipart/related або multipart/alternative (якщо вони явно не позначені як вкладення через Content-Disposition: attachment), і повернути всі інші частини. При безпосередньому застосуванні до multipart/related повертає ітератор для всіх пов’язаних частин, крім кореневої частини (тобто: частини, на яку вказує параметр start, або першої частини, якщо її немає Параметр start або параметр start не відповідає Content-ID жодної з частин). При застосуванні безпосередньо до multipart/alternative або не-multipart повертає порожній ітератор.

iter_parts()

Повертає ітератор для всіх безпосередніх підчастин повідомлення, який буде порожнім для не-multipart. (Див. також walk().)

get_content(*args, content_manager=None, **kw)

Викличте метод get_content() content_manager, передаючи self як об’єкт повідомлення та передаючи будь-які інші аргументи чи ключові слова як додаткові аргументи. Якщо content_manager не вказано, використовуйте content_manager, визначений поточною policy.

set_content(*args, content_manager=None, **kw)

Викличте метод set_content() content_manager, передаючи self як об’єкт повідомлення та передаючи будь-які інші аргументи чи ключові слова як додаткові аргументи. Якщо content_manager не вказано, використовуйте content_manager, визначений поточною policy.

Перетворіть повідомлення, яке не є складним, на багаточастинне/пов’язане повідомлення, перемістивши будь-які існуючі заголовки Content- і корисне навантаження в (нову) першу частину багаточастинного. Якщо вказано межу, використовуйте її як обмежувальний рядок у складеній частині, інакше залиште межу автоматично створеною, коли це необхідно (наприклад, коли повідомлення серіалізовано).

make_alternative(boundary=None)

Перетворіть не multipart або multipart/related на multipart/alternative, перемістивши всі наявні заголовки Content- і корисне навантаження в (нову) першу частину багаточастинний. Якщо вказано межу, використовуйте її як обмежувальний рядок у складеній частині, інакше залиште межу автоматично створеною, коли це необхідно (наприклад, коли повідомлення серіалізовано).

make_mixed(boundary=None)

Перетворіть не multipart, multipart/related або multipart-alternative на multipart/mixed, перемістивши будь-які існуючі заголовки Content- та корисне навантаження в (нову) першу частину multipart. Якщо вказано межу, використовуйте її як обмежувальний рядок у складеній частині, інакше залиште межу автоматично створеною, коли це необхідно (наприклад, коли повідомлення серіалізовано).

Якщо повідомлення є multipart/related, створіть новий об’єкт повідомлення, передайте всі аргументи його методу set_content() і attach() його до багаточастинний. Якщо повідомлення не є складним, викличте make_related(), а потім виконайте описані вище дії. Якщо повідомлення має будь-який інший тип multipart, викликайте TypeError. Якщо content_manager не вказано, використовуйте content_manager, визначений поточною policy. Якщо додана частина не має заголовка Content-Disposition, додайте його зі значенням inline.

add_alternative(*args, content_manager=None, **kw)

Якщо повідомлення є multipart/alternative, створіть новий об’єкт повідомлення, передайте всі аргументи його методу set_content() і attach() його до багаточастинний. Якщо повідомлення не є multipart або multipart/related, викличте make_alternative(), а потім виконайте описані вище дії. Якщо повідомлення має будь-який інший тип multipart, викликайте TypeError. Якщо content_manager не вказано, використовуйте content_manager, визначений поточною policy.

add_attachment(*args, content_manager=None, **kw)

Якщо повідомлення є multipart/mixed, створіть новий об’єкт повідомлення, передайте всі аргументи його методу set_content() і attach() його до багаточастинний. Якщо повідомлення не є multipart, multipart/related або multipart/alternative, викличте make_mixed(), а потім виконайте описані вище дії. Якщо content_manager не вказано, використовуйте content_manager, визначений поточною policy. Якщо додана частина не має заголовка Content-Disposition, додайте його зі значенням attachment. Цей метод можна використовувати як для явних вкладень (Content-Disposition: attachment), так і для вкладень inline (Content-Disposition: inline), передавши відповідні параметри content_manager.

clear()

Видаліть корисне навантаження та всі заголовки.

clear_content()

Remove the payload and all of the !Content- headers, leaving all other headers intact and in their original order.

Об’єкти EmailMessage мають такі атрибути екземпляра:

preamble

Формат документа MIME допускає деякий текст між порожнім рядком після заголовків і першим обмежувальним рядком із складених частин. Зазвичай цей текст ніколи не відображається в програмі читання пошти з підтримкою MIME, оскільки він виходить за межі стандартної броні MIME. Однак під час перегляду необробленого тексту повідомлення або під час перегляду повідомлення в програмі читання, яка не підтримує MIME, цей текст може стати видимим.

Атрибут преамбула містить цей провідний додатковий текст для документів MIME. Коли Parser виявляє текст після заголовків, але перед першим обмежувальним рядком, він призначає цей текст атрибуту преамбула повідомлення. Коли Generator записує звичайне текстове представлення повідомлення MIME і виявляє, що повідомлення має атрибут преамбула, він записує цей текст у область між заголовками та перша межа. Перегляньте email.parser і email.generator для деталей.

Зауважте, що якщо об’єкт повідомлення не має преамбули, атрибут preamble матиме значення None.

epilogue

Атрибут epilogue діє так само, як і атрибут preamble, за винятком того, що він містить текст, який з’являється між останньою межею та кінцем повідомлення. Як і у випадку з preamble, якщо немає тексту епілога, цей атрибут буде None.

defects

Атрибут defects містить список усіх проблем, виявлених під час аналізу цього повідомлення. Перегляньте email.errors для детального опису можливих дефектів аналізу.

class email.message.MIMEPart(policy=default)

Цей клас представляє підчастину повідомлення MIME. Він ідентичний EmailMessage, за винятком того, що під час виклику set_content() не додаються заголовки MIME-Version, оскільки підчастини не потребують власного Заголовки MIME-Version.

Виноски