email.header: Интернационализированные заголовки

Источник: Lib/email/header.py


Этот модуль является частью устаревшего (Compat32) почтового API. В текущем API кодирование и декодирование заголовков обрабатывается прозрачно с помощью API класса EmailMessage, похожего на словарь. Помимо использования в устаревшем коде, этот модуль может быть полезен в приложениях, которым необходимо полностью контролировать наборы символов, используемые при кодировании заголовков.

Остальной текст в этом разделе представляет собой оригинальную документацию модуля.

RFC 2822 - базовый стандарт, описывающий формат почтовых сообщений. Он берет начало от более старого стандарта RFC 822, который широко использовался в то время, когда большинство электронных сообщений состояло только из символов ASCII. RFC 2822 - это спецификация, написанная с учетом того, что электронная почта содержит только 7-битные символы ASCII.

Конечно, с распространением электронной почты по всему миру она стала интернационализированной, так что теперь в почтовых сообщениях можно использовать наборы символов, характерные для разных языков. Базовый стандарт по-прежнему требует, чтобы сообщения электронной почты передавались с использованием только 7-битных символов ASCII, поэтому был написан целый ряд RFC, описывающих, как кодировать сообщения электронной почты, содержащие символы, отличные от ASCII, в RFC 2822-совместимый формат. К таким RFC относятся RFC 2045, RFC 2046, RFC 2047 и RFC 2231. Пакет email поддерживает эти стандарты в своих модулях email.header и email.charset.

Если вы хотите включить в заголовки электронной почты символы, отличные от ASCII, например, в поля Subject или To, вам следует использовать класс Header и назначить поле в объекте Message экземпляру Header, а не использовать строку для значения заголовка. Импортируйте класс Header из модуля email.header. Например:

>>> from email.message import Message
>>> from email.header import Header
>>> msg = Message()
>>> h = Header('p\xf6stal', 'iso-8859-1')
>>> msg['Subject'] = h
>>> msg.as_string()
'Subject: =?iso-8859-1?q?p=F6stal?=\n\n'

Заметили, как мы хотели, чтобы поле Subject содержало символ, отличный от ASCII? Для этого мы создали экземпляр Header и передали в него набор символов, в котором была закодирована байтовая строка. Когда последующий экземпляр Message был сплющен, поле Subject получило правильную кодировку RFC 2047. Программы чтения почты, поддерживающие MIME, отображали этот заголовок с использованием встроенного символа ISO-8859-1.

Вот описание класса Header:

class email.header.Header(s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' ', errors='strict')

Создайте MIME-совместимый заголовок, который может содержать строки в различных наборах символов.

Необязательное значение s - начальное значение заголовка. Если None (по умолчанию), начальное значение заголовка не задается. Впоследствии вы можете добавить его к заголовку с помощью вызовов метода append(). s может быть экземпляром bytes или str, но семантику см. в документации append().

Необязательный charset служит двум целям: он имеет то же значение, что и аргумент charset метода append(). Он также задает набор символов по умолчанию для всех последующих вызовов append(), в которых аргумент charset опущен. Если charset не указан в конструкторе (по умолчанию), набор символов us-ascii используется как в качестве начального набора символов s, так и по умолчанию для последующих вызовов append().

Максимальная длина строки может быть задана явно через maxlinelen. Для разбиения первой строки на более короткие значения (для учета заголовка поля, не включенного в s, например, Subject) передайте имя поля в header_name. По умолчанию maxlinelen равно 76, а значение по умолчанию для header_name равно None, что означает, что оно не учитывается для первой строки длинного разделенного заголовка.

Необязательный символ continuation_ws должен быть RFC 2822- совместимым со сворачиванием пробельных символов, и обычно представляет собой либо пробел, либо символ жесткой табуляции. Этот символ будет добавляться к строкам продолжения. По умолчанию continuation_ws - это один символ пробела.

Необязательные ошибки передаются прямо в метод append().

append(s, charset=None, errors='strict')

Добавьте строку s к заголовку MIME.

Необязательное значение charset, если оно задано, должно быть экземпляром Charset (см. email.charset) или именем набора символов, которое будет преобразовано в экземпляр Charset. Значение None (по умолчанию) означает, что используется charset, заданный в конструкторе.

s может быть экземпляром bytes или str. Если это экземпляр bytes, то charset - это кодировка этой байтовой строки, и если строка не может быть декодирована с помощью этого набора символов, то будет вызвана ошибка UnicodeError.

Если s - это экземпляр str, то charset - это подсказка, указывающая набор символов в строке.

В любом случае, при создании RFC 2822-совместимого заголовка с использованием правил RFC 2047 строка будет закодирована с помощью выходного кодека кодовой сетки. Если строка не может быть закодирована с помощью выходного кодека, будет выдана ошибка UnicodeError.

Необязательная errors передается в качестве аргумента errors вызову декодирования, если s - байтовая строка.

encode(splitchars=';, \t', maxlinelen=None, linesep='\n')

Кодирование заголовка сообщения в RFC-совместимый формат, возможно, обертывание длинных строк и инкапсуляция не-ASCII частей в base64 или quoted-printable кодировках.

Необязательные splitchars - это строка, содержащая символы, которым алгоритм разбиения должен придавать дополнительный вес при обычном обертывании заголовка. Это очень грубая поддержка RFC 2822«синтаксических разрывов более высокого уровня»: точки разделения, которым предшествует сплитчар, предпочитаются при разбиении строки, причем символы предпочитаются в том порядке, в котором они появляются в строке. Пробел и табуляция могут быть включены в строку, чтобы указать, следует ли отдавать предпочтение одному из них перед другим в качестве точки разделения, когда другие символы разделения не встречаются в разделяемой строке. Splitchars не влияет на строки с кодировкой RFC 2047.

maxlinelen, если задано, переопределяет значение экземпляра для максимальной длины строки.

linesep задает символы, используемые для разделения строк свернутого заголовка. По умолчанию используется наиболее удобное значение для кода приложений Python (\n), но можно указать \r\n, чтобы получить заголовки с разделителями строк, соответствующими RFC.

Изменено в версии 3.2: Добавлен аргумент linesep.

Класс Header также предоставляет ряд методов для поддержки стандартных операторов и встроенных функций.

__str__()

Возвращает приближенное значение Header в виде строки, используя неограниченную длину строки. Все фрагменты преобразуются в юникод с использованием указанной кодировки и соединяются соответствующим образом. Все фрагменты с кодировкой 'unknown-8bit' декодируются как ASCII с помощью обработчика ошибок 'replace'.

Изменено в версии 3.2: Добавлена обработка набора символов 'unknown-8bit'.

__eq__(other)

Этот метод позволяет сравнить два экземпляра Header на равенство.

__ne__(other)

Этот метод позволяет сравнить два экземпляра Header на предмет неравенства.

Модуль email.header также предоставляет следующие удобные функции.

email.header.decode_header(header)

Декодирование значения заголовка сообщения без преобразования набора символов. Значение заголовка находится в header.

Эта функция возвращает список пар (decoded_string, charset), содержащих каждую из декодированных частей заголовка. charset - None для некодированных частей заголовка, иначе строка в нижнем регистре, содержащая имя набора символов, указанного в кодированной строке.

Вот пример:

>>> from email.header import decode_header
>>> decode_header('=?iso-8859-1?q?p=F6stal?=')
[(b'p\xf6stal', 'iso-8859-1')]
email.header.make_header(decoded_seq, maxlinelen=None, header_name=None, continuation_ws=' ')

Создайте экземпляр Header из последовательности пар, возвращенных decode_header().

decode_header() принимает строку значений заголовка и возвращает последовательность пар формата (decoded_string, charset), где charset - имя набора символов.

Эта функция принимает одну из таких пар и возвращает экземпляр Header. Необязательные параметры maxlinelen, header_name и continuation_ws - как в конструкторе Header.