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


Добавлено в версии 3.6: [1]

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

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

Концептуальная модель, предоставляемая объектом EmailMessage, представляет собой модель упорядоченного словаря заголовков в сочетании с полезной нагрузкой, представляющим тело сообщения RFC 5322, которое может быть списком подобъектов EmailMessage. В дополнение к обычным методам словаря для доступа к именам и значениям заголовков существуют методы для доступа к специализированной информации из заголовков (например, тип содержимого MIME), для работы с полезной нагрузкой, для создания сериализованной версии сообщения и для рекурсивного обхода дерева объектов.

Подобный словарю интерфейс EmailMessage индексируется именами заголовков, которые должны быть ASCII значениями. Значения словаря представляют собой строки с некоторыми дополнительными методами. Заголовки сохраняются и возвращаются в форме с сохранением регистра, но имена полей сопоставляются без учёта регистра. В отличие от настоящего dict, ключи упорядочиваются, и могут быть дубликаты ключей. Предусмотрены дополнительные методы для работы с заголовками, имеющими повторяющиеся ключи.

Полезная нагрузка — это объект строки или байтов в случае простых объектов сообщений или список объектов EmailMessage для MIME документов-контейнеров, таких как объекты сообщений multipart/* и message/rfc822.

class email.message.EmailMessage(policy=default)

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

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

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

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

Обратите внимание, что данный метод предоставляется для удобства и может быть не самым полезным способом сериализации сообщений в вашем приложении, особенно если вы имеете дело с несколькими сообщениями. См. email.generator.Generator для более гибкого API для сериализации сообщений. Также обратите внимание, что данный метод ограничен созданием сообщений, сериализованных как «7-битные чистые», когда 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)

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

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

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

__bytes__()

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

is_multipart()

Возвращает True, если полезная нагрузка сообщения представляет собой список объектов под-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. Соответствие выполняется без учета регистра, а name не включает завершающее двоеточие. Используется для оператора in. Например:

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

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

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

При использовании стандартных (не compat32) политик возвращаемое значение является экземпляром подкласса email.headerregistry.BaseHeader.

__setitem__(name, val)

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

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

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

Если policy определяет определённые заголовки как уникальные (как это делают стандартные политики), данный метод может вызвать ValueError при попытке присвоить значение такому заголовку, когда он уже существует. Это поведение преднамеренно для обеспечения согласованности, но не зависит от него, поскольку мы можем сделать так, чтобы такие назначения автоматически удаляли существующий заголовок в будущем.

__delitem__(name)

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

keys()

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

values()

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

items()

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

get(name, failobj=None)

Возвращает значение именованного поля заголовка. Это идентично __getitem__(), за исключением того, что необязательный failobj возвращается, если именованный заголовок отсутствует (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'))
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. Необязательный language указывает язык RFC 2231, по умолчанию используется пустая строка. И charset, и language должны быть строками. По умолчанию используются utf8 charset и None для language.

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

Использование параметра requote с объектами EmailMessage не рекомендуется.

Обратите внимание, что доступ к существующим значениям параметров заголовков можно получить через атрибут params значения заголовка (например, msg['Content-Type'].params['charset']).

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

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

Полностью удаляет данный параметр из заголовка Content- Type. Заголовок будет перезаписан на месте без параметра или его значения. Необязательный header указывает альтернативу 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.

Добавлено в версии 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, передав себя в качестве объекта сообщения и передав любые другие позиционные или ключевые аргументы в качестве дополнительных аргументов. Если content_manager не указан, используйте content_manager, указанный текущим policy.

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

Вызывает метод set_content() content_manager, передав себя в качестве объекта сообщения и передав любые другие позиционные или ключевые аргументы в качестве дополнительных аргументов. Если content_manager не указан, используйте content_manager, указанный текущим policy.

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

make_alternative(boundary=None)

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

make_mixed(boundary=None)

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

Если сообщение является multipart/related, создаёт новый объект сообщения, передать все аргументы его методу set_content(), а attach() — в multipart. Если сообщение не является multipart, вызывает 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 или 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, 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()

Удаляет полезные данные и все заголовки Content-, оставив все остальные заголовки нетронутыми и в их первоначальном порядке.

Объекты EmailMessage имеют следующие атрибуты экземпляра:

preamble

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

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

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

epilogue

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

defects

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

class email.message.MIMEPart(policy=default)

Данный класс представляет собой часть MIME сообщения. Он идентичен EmailMessage, за исключением того, что заголовки MIME-Version не добавляются при вызове set_content(), поскольку подчастям не нужны собственные заголовки MIME-Version.

Ссылки

[1]Первоначально добавлен в 3.4 как предварительный пакет. Документы для устаревшего класса сообщений перемещены в email.message.Message: Представление сообщения электронной почты с помощью API compat32.