email.message.Message: Представление сообщения электронной почты с помощью compat32. API

Класс Message очень похож на класс EmailMessage, но без методов, добавленных этим классом, и с несколько иным поведением по умолчанию некоторых других методов. Мы также документируем здесь некоторые методы, которые, хотя и поддерживаются классом EmailMessage, не рекомендуется использовать, если вы не имеете дело с устаревшим кодом.

В остальном философия и структура этих двух классов одинаковы.

Этот документ описывает поведение политики Compat32, используемой по умолчанию (для Message). Если вы собираетесь использовать другую политику, то вместо нее следует использовать класс EmailMessage.

Сообщение электронной почты состоит из заголовков и груза. Заголовки должны иметь имена и значения в стиле RFC 5322, где имя поля и значение разделены двоеточием. Двоеточие не является частью ни имени поля, ни его значения. Полезная нагрузка может быть простым текстовым сообщением, или двоичным объектом, или структурированной последовательностью под-сообщений, каждое из которых имеет свой набор заголовков и свою полезную нагрузку. На последний тип полезной нагрузки указывает наличие у сообщения MIME-типа, например multipart/* или message/rfc822.

Концептуальная модель, предоставляемая объектом Message, представляет собой упорядоченный словарь заголовков с дополнительными методами для доступа к специализированной информации из заголовков, для доступа к полезной нагрузке, для генерации сериализованной версии сообщения и для рекурсивного перехода по дереву объектов. Обратите внимание, что поддерживаются дубликаты заголовков, но для доступа к ним необходимо использовать специальные методы.

Псевдословарь Message индексируется по именам заголовков, которые должны быть ASCII-значениями. Значения словаря - это строки, которые должны содержать только ASCII-символы; для ввода не ASCII существует специальная обработка, но она не всегда дает правильные результаты. Заголовки хранятся и возвращаются в форме, сохраняющей регистр, но имена полей сопоставляются без учета регистра. Также может быть один заголовок конверта, также известный как заголовок Unix-From или заголовок From_. Груз* - это либо строка или байт, в случае простых объектов сообщений, либо список объектов Message для документов-контейнеров MIME (например, multipart/* и message/rfc822).

Вот методы класса Message:

class email.message.Message(policy=compat32)

Если указана policy (она должна быть экземпляром класса policy), используйте указанные в ней правила для обновления и сериализации представления сообщения. Если policy не задана, используйте политику compat32, которая поддерживает обратную совместимость с версией почтового пакета Python 3.2. Для получения дополнительной информации см. документацию по policy.

Изменено в версии 3.3: Добавлен аргумент с ключевым словом policy.

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

Возвращает все сообщение, сглаженное в виде строки. Если необязательное значение unixfrom равно true, заголовок конверта будет включен в возвращаемую строку. Значение unixfrom по умолчанию равно False. По соображениям обратной совместимости maxheaderlen по умолчанию принимает значение 0, поэтому, если вам нужно другое значение, вы должны явно переопределить его (значение, указанное для max_line_length в политике, будет проигнорировано этим методом). Аргумент policy может быть использован для переопределения политики по умолчанию, полученной от экземпляра сообщения. Это может быть использовано для управления некоторым форматированием, производимым методом, поскольку указанная политика будет передана в Generator.

Сплющивание сообщения может вызвать изменения в Message, если необходимо заполнить значения по умолчанию для завершения преобразования в строку (например, могут быть созданы или изменены границы MIME).

Обратите внимание, что этот метод предоставляется в качестве удобства и не всегда может отформатировать сообщение так, как вам нужно. Например, по умолчанию он не выполняет обработку строк, начинающихся с From, которая требуется в формате Unix mbox. Для большей гибкости создайте экземпляр Generator и используйте его метод flatten() напрямую. Например:

from io import StringIO
from email.generator import Generator
fp = StringIO()
g = Generator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

Если объект сообщения содержит двоичные данные, которые не закодированы в соответствии со стандартами RFC, несоответствующие данные будут заменены кодовыми точками «неизвестный символ» Юникода. (См. также as_bytes() и BytesGenerator).

Изменено в версии 3.4: был добавлен аргумент с ключевым словом policy.

__str__()

Эквивалентно as_string(). Позволяет str(msg) выдавать строку, содержащую отформатированное сообщение.

as_bytes(unixfrom=False, policy=None)

Возвращает все сообщение, сплющенное в виде объекта bytes. Если необязательное значение unixfrom равно true, заголовок конверта будет включен в возвращаемую строку. По умолчанию unixfrom принимает значение False. Аргумент policy может быть использован для переопределения политики по умолчанию, полученной из экземпляра сообщения. Это может быть использовано для управления некоторым форматированием, производимым методом, поскольку указанная политика будет передана в BytesGenerator.

Сплющивание сообщения может вызвать изменения в Message, если необходимо заполнить значения по умолчанию для завершения преобразования в строку (например, могут быть созданы или изменены границы MIME).

Обратите внимание, что этот метод предоставляется в качестве удобства и не всегда может отформатировать сообщение так, как вам нужно. Например, по умолчанию он не выполняет обработку строк, начинающихся с From, которая требуется в формате Unix mbox. Для большей гибкости создайте экземпляр BytesGenerator и используйте его метод flatten() напрямую. Например:

from io import BytesIO
from email.generator import BytesGenerator
fp = BytesIO()
g = BytesGenerator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

Added in version 3.4.

__bytes__()

Эквивалентно as_bytes(). Позволяет bytes(msg) создавать объект bytes, содержащий отформатированное сообщение.

Added in version 3.4.

is_multipart()

Возвращает True, если полезная нагрузка сообщения представляет собой список объектов sub-Message, в противном случае возвращает False. Если is_multipart() возвращает False, полезная нагрузка должна быть строковым объектом (который может быть двоичным объектом, закодированным в CTE). (Обратите внимание, что is_multipart(), возвращающий True, не обязательно означает, что «msg.get_content_maintype() == „multipart“» вернет True. Например, is_multipart вернет True, если Message имеет тип message/rfc822).

set_unixfrom(unixfrom)

Установите в заголовке конверта сообщения значение unixfrom, которое должно быть строкой.

get_unixfrom()

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

attach(payload)

Добавляет заданную платежную нагрузку к текущей полезной нагрузке, которая до вызова должна быть None или списком объектов Message. После вызова полезная нагрузка всегда будет списком объектов Message. Если вы хотите установить полезную нагрузку в скалярный объект (например, строку), используйте вместо этого set_payload().

Это унаследованный метод. В классе EmailMessage его функциональность заменена на set_content() и связанные с ним методы make и add.

get_payload(i=None, decode=False)

Возвращает текущую полезную нагрузку, которая будет представлять собой список объектов Message, если is_multipart() - True, или строку, если is_multipart() - False. Если полезная нагрузка представляет собой список и вы мутируете объект списка, вы изменяете полезную нагрузку сообщения.

При необязательном аргументе i get_payload() вернет i-й элемент полезной нагрузки, считая от нуля, если is_multipart() - True. Если i меньше 0 или больше или равно количеству элементов в полезной нагрузке, будет вызвана ошибка IndexError. Если полезная нагрузка является строкой (например, is_multipart() является False) и задано i, то будет вызван сигнал TypeError.

Необязательный decode - это флаг, указывающий, следует ли декодировать полезную нагрузку или нет, в соответствии с заголовком Content-Transfer-Encoding. Если значение True и сообщение не является многокомпонентным, полезная нагрузка будет декодирована, если значение этого заголовка равно quoted-printable или base64. Если используется другая кодировка или заголовок Content-Transfer-Encoding отсутствует, полезная нагрузка возвращается как есть (не декодированной). Во всех случаях возвращаемое значение представляет собой двоичные данные. Если сообщение является многокомпонентным и флаг decode равен True, то возвращается None. Если полезная нагрузка имеет формат base64 и она была сформирована не идеально (отсутствует подложка, символы вне алфавита base64), то к свойству дефекта сообщения будет добавлен соответствующий дефект (InvalidBase64PaddingDefect или InvalidBase64CharactersDefect, соответственно).

Если значение decode равно False (по умолчанию), тело возвращается в виде строки без декодирования Content-Transfer-Encoding. Однако при значении Content-Transfer-Encoding, равном 8 бит, предпринимается попытка декодировать исходные байты с помощью charset, указанного в заголовке Content-Type, используя обработчик ошибок replace. Если charset не указан, или если указанный charset не распознан почтовым пакетом, тело сообщения декодируется с использованием стандартной кодировки ASCII.

Это устаревший метод. В классе EmailMessage его функциональность заменена на get_content() и iter_parts().

set_payload(payload, charset=None)

Устанавливает всю полезную нагрузку объекта сообщения в payload. Ответственность за обеспечение инвариантов полезной нагрузки лежит на клиенте. Необязательный charset задает набор символов сообщения по умолчанию; подробности см. в set_charset().

Это унаследованный метод. В классе EmailMessage его функциональность заменена на set_content().

set_charset(charset)

Установите набор символов полезной нагрузки в charset, который может быть либо экземпляром Charset (см. email.charset), либо строкой с именем набора символов, либо None. Если это строка, она будет преобразована в экземпляр Charset. Если charset - это None, то параметр charset будет удален из заголовка Content-Type (сообщение не будет изменено никаким другим образом). Любое другое значение приведет к появлению TypeError.

Если нет существующего заголовка MIME-Version, он будет добавлен. Если нет существующего заголовка Content-Type, он будет добавлен со значением text/plain. Независимо от того, существует ли уже заголовок Content-Type или нет, его параметр charset будет установлен в charset.output_charset. Если charset.input_charset и charset.output_charset отличаются, полезная нагрузка будет перекодирована в output_charset. Если нет существующего заголовка Content-Transfer-Encoding, то полезная нагрузка будет перекодирована, если необходимо, с использованием указанного Charset, и будет добавлен заголовок с соответствующим значением. Если заголовок Content-Transfer-Encoding уже существует, считается, что полезная нагрузка уже правильно закодирована с помощью этого Content-Transfer-Encoding, и она не изменяется.

Это устаревший метод. В классе EmailMessage его функциональность заменена параметром charset метода email.emailmessage.EmailMessage.set_content().

get_charset()

Возвращает экземпляр Charset, связанный с полезной нагрузкой сообщения.

Это унаследованный метод. В классе EmailMessage он всегда возвращает None.

Следующие методы реализуют интерфейс, подобный маппингу, для доступа к заголовкам RFC 2822 сообщения. Обратите внимание, что между этими методами и обычным интерфейсом отображения (т. е. словарем) есть некоторые семантические различия. Например, в словаре нет дублирующихся ключей, а здесь могут быть дублирующиеся заголовки сообщений. Кроме того, в словарях нет гарантированного порядка ключей, возвращаемых keys(), но в объекте Message заголовки всегда возвращаются в том порядке, в котором они появились в исходном сообщении или были добавлены к нему позже. Любой заголовок, удаленный, а затем вновь добавленный, всегда добавляется в конец списка заголовков.

Эти семантические различия намеренны и направлены на максимальное удобство.

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

В модели, созданной на основе байтов, любые значения заголовков, которые (в нарушение RFC) содержат байты, отличные от ASCII, при получении через этот интерфейс будут представлены как объекты Header с кодовой сеткой unknown-8bit.

__len__()

Возвращает общее количество заголовков, включая дубликаты.

__contains__(name)

Возвращает True, если объект сообщения имеет поле с именем name. Поиск осуществляется без учета регистра, и name не должно содержать двоеточие в конце. Используется для оператора in, например:

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

Возвращает значение именованного поля заголовка. Имя не должно включать разделитель полей двоеточие. Если заголовок отсутствует, возвращается значение None; значение KeyError не возвращается.

Обратите внимание, что если именованное поле встречается в заголовках сообщения более одного раза, то какое именно из значений этого поля будет возвращено, не определено. Используйте метод get_all(), чтобы получить значения всех существующих именованных заголовков.

__setitem__(name, val)

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

Обратите внимание, что при этом не перезаписываются или удаляются существующие заголовки с тем же именем. Если вы хотите, чтобы новый заголовок был единственным, присутствующим в сообщении с именем поля name, сначала удалите это поле, например:

del msg['subject']
msg['subject'] = 'Python roolz!'
__delitem__(name)

Удаляет все вхождения поля с именем name из заголовков сообщения. Если именованное поле не присутствует в заголовках, исключение не возникает.

keys()

Возвращает список имен всех полей заголовков сообщения.

values()

Возвращает список всех значений полей сообщения.

items()

Возвращает список из 2 кортежей, содержащих все заголовки и значения полей сообщения.

get(name, failobj=None)

Возвращает значение именованного поля заголовка. Это идентично __getitem__(), за исключением того, что возвращается необязательное значение failobj, если именованный заголовок отсутствует (по умолчанию None).

Вот несколько дополнительных полезных методов:

get_all(name, failobj=None)

Возвращает список всех значений для поля с именем name. Если в сообщении нет таких именованных заголовков, возвращается failobj (по умолчанию None).

add_header(_name, _value, **_params)

Расширенная настройка заголовка. Этот метод аналогичен __setitem__(), за исключением того, что дополнительные параметры заголовка могут быть предоставлены в качестве аргументов ключевых слов. _name - это поле заголовка, которое нужно добавить, а _value - это основное значение для заголовка.

Для каждого элемента словаря аргументов _params в качестве имени параметра берется ключ, а подчеркивание преобразуется в тире (поскольку тире в идентификаторах Python недопустимо). Обычно параметр добавляется в виде key="value", если только значение не равно None, в этом случае добавляется только ключ. Если значение содержит не-ASCII символы, оно может быть задано в виде кортежа в формате (CHARSET, LANGUAGE, VALUE), где CHARSET - строка, называющая кодировку значения, LANGUAGE обычно может быть задана как None или пустая строка (см. RFC 2231 для других возможностей), а VALUE - строковое значение, содержащее не-ASCII кодовые точки. Если не передается кортеж из трех, а значение содержит не-ASCII символы, оно автоматически кодируется в формате RFC 2231 с использованием CHARSET из utf-8 и LANGUAGE из None.

Вот пример:

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'))

Который производит

Content-Disposition: attachment; filename*="iso-8859-1''Fu%DFballer.ppt"
replace_header(_name, _value)

Заменить заголовок. Заменяет первый найденный в сообщении заголовок, который соответствует _имя, сохраняя порядок заголовков и регистр имен полей. Если подходящего заголовка не найдено, выдается сообщение KeyError.

get_content_type()

Возвращает тип содержимого сообщения. Возвращаемая строка приводится к нижнему регистру в виде maintype/subtype. Если в сообщении не было заголовка Content-Type, то будет возвращен тип по умолчанию, заданный в get_default_type(). Поскольку, согласно 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_params(failobj=None, header='content-type', unquote=True)

Возвращает параметры Content-Type сообщения в виде списка. Элементами возвращаемого списка являются 2-кортежи пар ключ/значение, разделенные по признаку '='. Левая часть '=' - это ключ, а правая - значение. Если в параметре нет знака '=', то значением будет пустая строка, иначе значение будет таким, как описано в get_param(), и будет без кавычек, если опциональная unquote равна True (по умолчанию).

Необязательный failobj - объект, который возвращается, если нет заголовка Content-Type. Необязательный header - заголовок, который следует искать вместо Content-Type.

Это унаследованный метод. В классе EmailMessage его функциональность заменена свойством params отдельных объектов заголовков, возвращаемых методами доступа к заголовкам.

get_param(param, failobj=None, header='content-type', unquote=True)

Возвращает значение параметра param заголовка Content-Type в виде строки. Если сообщение не имеет заголовка Content-Type или если такой параметр отсутствует, то возвращается значение failobj (по умолчанию None).

Необязательный header, если задан, указывает заголовок сообщения, который следует использовать вместо Content-Type.

Ключи параметров всегда сравниваются без учета регистра. Возвращаемое значение может быть либо строкой, либо 3-кортежем, если параметр был закодирован RFC 2231. Если это 3-кортеж, то элементы значения имеют вид (CHARSET, LANGUAGE, VALUE). Обратите внимание, что и CHARSET, и LANGUAGE могут быть None, и в этом случае следует считать, что VALUE закодирован в кодировке us-ascii. Обычно LANGUAGE можно игнорировать.

Если вашему приложению все равно, был ли параметр закодирован, как в RFC 2231, вы можете свернуть значение параметра, вызвав email.utils.collapse_rfc2231_value() и передав возвращаемое значение из get_param(). Это вернет соответствующим образом декодированную строку Unicode, если значение представляет собой кортеж, или исходную строку без кавычек, если это не так. Например:

rawparam = msg.get_param('foo')
param = email.utils.collapse_rfc2231_value(rawparam)

В любом случае значение параметра (либо возвращаемая строка, либо элемент VALUE в 3 кортеже) всегда остается без кавычек, если только для параметра unquote не установлено значение False.

Это унаследованный метод. В классе EmailMessage его функциональность заменена свойством params отдельных объектов заголовков, возвращаемых методами доступа к заголовкам.

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

Устанавливает параметр в заголовке Content-Type. Если параметр уже существует в заголовке, его значение будет заменено на value. Если заголовок Content-Type еще не определен для этого сообщения, он будет установлен в text/plain, а новое значение параметра будет добавлено в соответствии с RFC 2045.

Необязательное значение header указывает альтернативный заголовок Content-Type, и все параметры будут заключены в кавычки, если необязательное значение requote не равно False (по умолчанию True).

Если указан необязательный charset, параметр будет закодирован в соответствии с RFC 2231. Необязательный language задает язык RFC 2231, по умолчанию - пустая строка. И charset, и language должны быть строками.

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

Изменено в версии 3.4: Было добавлено ключевое слово replace.

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

Полностью удаляет заданный параметр из заголовка Content-Type. Заголовок будет переписан на место без параметра или его значения. Все значения будут заключены в кавычки, если только параметр requote не равен False (по умолчанию True). Необязательный параметр header указывает альтернативу Content-Type.

set_type(type, header='Content-Type', requote=True)

Устанавливает основной тип и подтип для заголовка Content-Type. type должен быть строкой в форме maintype/subtype, в противном случае возникает ошибка ValueError.

Этот метод заменяет заголовок Content-Type, сохраняя все параметры. Если requote имеет значение False, то кавычки в существующем заголовке останутся на месте, в противном случае параметры будут заключены в кавычки (по умолчанию).

Альтернативный заголовок может быть указан в аргументе header. При установке заголовка Content-Type также добавляется заголовок MIME-Version.

Это унаследованный метод. В классе EmailMessage его функциональность заменена методами make_ и add_.

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. Если объект сообщения не имеет заголовка Content-Type, возникает ошибка HeaderParseError.

Обратите внимание, что использование этого метода несколько отличается от удаления старого заголовка Content-Type и добавления нового с новой границей с помощью add_header(), поскольку set_boundary() сохраняет порядок заголовка Content-Type в списке заголовков. Однако она не сохраняет никаких строк продолжения, которые могли присутствовать в исходном заголовке Content-Type.

get_content_charset(failobj=None)

Возвращает параметр charset заголовка Content-Type, приведенный к нижнему регистру. Если заголовок Content-Type отсутствует или у него нет параметра charset, возвращается failobj.

Обратите внимание, что этот метод отличается от get_charset(), который возвращает экземпляр Charset для кодировки тела сообщения по умолчанию.

get_charsets(failobj=None)

Возвращает список, содержащий имена наборов символов в сообщении. Если сообщение является multipart, то список будет содержать по одному элементу для каждого подраздела в полезной нагрузке, в противном случае это будет список длины 1.

Каждый элемент в списке будет строкой, которая является значением параметра charset в заголовке Content-Type для представленного подраздела. Однако, если подраздел не имеет заголовка Content-Type, параметра charset или не относится к основному MIME-типу text, то этот элемент в возвращаемом списке будет failobj.

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 для отладки:

>>> 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 спускается в слагаемые.

Объекты Message также могут содержать два атрибута экземпляра, которые могут быть использованы при генерации обычного текста MIME-сообщения.

preamble

Формат MIME-документа допускает наличие некоторого текста между пустой строкой, следующей за заголовками, и первой многочастной граничной строкой. Обычно этот текст никогда не виден в программе чтения почты с поддержкой MIME, поскольку он выходит за рамки стандартных MIME-броней. Однако при просмотре необработанного текста сообщения или при просмотре сообщения в программе чтения, не поддерживающей MIME, этот текст может стать видимым.

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

Обратите внимание, что если объект сообщения не имеет преамбулы, атрибут preamble будет равен None.

epilogue

Атрибут epilogue действует так же, как и атрибут preamble, за исключением того, что он содержит текст, который появляется между последней границей и концом сообщения.

Для того чтобы Generator выводил новую строку в конце файла, не нужно устанавливать эпилог в пустую строку.

defects

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