Документация Python неофициальный перевод
Содержание страницы

18.11. rfc822 – Разбор заголовков почты RFC 2822rfc822 – Parse RFC 2822 mail headers

Устарело с версии 2.3: Пакет email следует использовать вместо модуля rfc822. Этот модуль существует только для поддержки обратной совместимости и удалён в Python 3.

Этот модуль определяет класс Message, который представляет «сообщение электронной почты», как определено в интернет-стандарте RFC 2822. 1 Такие сообщения состоят из набора заголовков и тела сообщения. В этом модуле также определён вспомогательный класс AddressList для разбора адресов RFC 2822. Обратитесь к RFC за информацией о конкретном синтаксисе сообщений RFC 2822.

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

class rfc822.Message(file[, seekable])

Экземпляр Message создаётся с входным объектом в качестве параметра. Message полагается только на то, что входной объект имеет метод readline(); в частности, подходят обычные файловые объекты. При создании экземпляра заголовки читаются из входного объекта до строки-разделителя (обычно пустой строки) и сохраняются в экземпляре. Тело сообщения, следующее за заголовками, не потребляется.

Этот класс может работать с любым входным объектом, поддерживающим метод readline(). Если входной объект имеет возможность seek и tell, будет работать метод rewindbody(); кроме того, некорректные строки будут возвращены обратно во входной поток. Если входной объект не имеет seek, но имеет метод unread(), который может вернуть строку обратно, Message будет использовать его для возврата некорректных строк. Таким образом, этот класс можно использовать для разбора сообщений, поступающих из буферизованного потока.

Необязательный аргумент seekable предоставляется как обходной путь для некоторых библиотек stdio, в которых tell() сбрасывает буферизованные данные, прежде чем обнаружить, что системный вызов lseek() не работает. Для максимальной переносимости следует установить аргумент seekable в ноль, чтобы предотвратить этот начальный tell() при передаче непозиционируемого объекта, например файлового объекта, созданного из объекта сокета.

Входные строки, читаемые из файла, могут заканчиваться либо CR-LF, либо одиночным переводом строки; завершающий CR-LF заменяется на одиночный перевод строки перед сохранением строки.

Все сравнения заголовков выполняются без учёта регистра; например, m['From'], m['from'] и m['FROM'] дают одинаковый результат.

class rfc822.AddressList(field)

Можно создать экземпляр вспомогательного класса AddressList, используя один строковый параметр – список адресов RFC 2822, разделённых запятыми, для разбора. (Параметр None даёт пустой список.)

rfc822.quote(str)

Возвращает новую строку, в которой обратная косая черта в str заменена на две обратные косые черты, а двойные кавычки – на обратную косую черту и двойную кавычку.

rfc822.unquote(str)

Возвращает новую строку, которая является расквотированной версией str. Если str начинается и заканчивается двойными кавычками, они удаляются. Аналогично, если str начинается и заканчивается угловыми скобками, они удаляются.

rfc822.parseaddr(address)

Разбирает address, который должен быть значением какого-либо поля, содержащего адрес, например To или Cc, на составные части – «имя» и «адрес электронной почты». Возвращает кортеж с этой информацией, если только разбор не завершается ошибкой; в этом случае возвращается кортеж из двух элементов (None, None).

rfc822.dump_address_pair(pair)

Обратная функция к parseaddr(), она принимает кортеж из двух элементов вида (realname, email_address) и возвращает строковое значение, подходящее для заголовка To или Cc. Если первый элемент pair равен false, то второй элемент возвращается без изменений.

rfc822.parsedate(date)

Пытается разобрать дату в соответствии с правилами RFC 2822. Однако некоторые почтовые программы не следуют этому формату, поэтому parsedate() пытается правильно угадать дату в таких случаях. date – это строка, содержащая дату в формате RFC 2822, например, 'Mon, 20 Nov 1995 19:12:08 -0500'. Если разбор даты успешен, parsedate() возвращает кортеж из 9 элементов, который можно напрямую передать в time.mktime(); в противном случае возвращается None. Обратите внимание, что индексы 6, 7 и 8 кортежа результата не пригодны для использования.

rfc822.parsedate_tz(date)

Выполняет ту же функцию, что и parsedate(), но возвращает либо None, либо кортеж из 10 элементов; первые 9 элементов образуют кортеж, который можно напрямую передать в time.mktime(), а десятый – смещение часового пояса даты относительно UTC (официальный термин для среднего времени по Гринвичу). (Обратите внимание, что знак смещения часового пояса противоположен знаку переменной time.timezone для того же часового пояса; последняя переменная соответствует стандарту POSIX, тогда как этот модуль следует RFC 2822.) Если входная строка не содержит часового пояса, последним элементом возвращаемого кортежа является None. Обратите внимание, что индексы 6, 7 и 8 результирующего кортежа не могут быть использованы.

rfc822.mktime_tz(tuple)

Преобразует кортеж из 10 элементов, возвращаемый функцией parsedate_tz(), во временную метку UTC. Если элемент часового пояса в кортеже равен None, предполагается местное время. Небольшой недостаток: сначала первые 8 элементов интерпретируются как местное время, а затем применяется поправка на разницу часовых поясов; это может привести к небольшой ошибке в даты перехода на летнее время. Но для обычного использования это несущественно.

См. также

Модуль email

Комплексный пакет для обработки электронной почты; заменяет модуль rfc822.

Модуль mailbox

Классы для чтения различных форматов почтовых ящиков, созданных пользовательскими почтовыми программами.

Модуль mimetools

Подкласс rfc822.Message, обрабатывающий сообщения в кодировке MIME.

18.11.1. Объекты сообщенийMessage Objects

Экземпляр Message имеет следующие методы:

Message.rewindbody()

Перейти к началу тела сообщения. Работает только если файловый объект поддерживает позиционирование.

Message.isheader(line)

Возвращает канонизированное имя поля строки (ключ словаря, который будет использоваться для индексации), если строка является допустимым заголовком RFC 2822; в противном случае возвращает None (что означает, что разбор должен остановиться, а строка должна быть возвращена во входной поток). Иногда бывает полезно переопределить этот метод в подклассе.

Message.islast(line)

Возвращает истину, если данная строка является разделителем, на котором Message должен остановиться. Строка-разделитель потребляется, а позиция чтения файлового объекта устанавливается сразу после неё. По умолчанию этот метод просто проверяет, что строка пуста, но его можно переопределить в подклассе.

Message.iscomment(line)

Возвращает True, если данную строку следует полностью игнорировать, просто пропустить. По умолчанию это заглушка, которая всегда возвращает False, но вы можете переопределить её в подклассе.

Message.getallmatchingheaders(name)

Возвращает список строк, содержащий все заголовки, соответствующие name, если они есть. Каждая физическая строка (строка продолжения или нет) является отдельным элементом списка. Возвращает пустой список, если ни один заголовок не соответствует name.

Message.getfirstmatchingheader(name)

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

Message.getrawheader(name)

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

Message.getheader(name[, default])

Возвращает одну строку, состоящую из последнего заголовка, соответствующего name, но с удалением начальных и конечных пробелов. Внутренние пробелы не удаляются. Необязательный аргумент default можно использовать для указания другого значения, возвращаемого при отсутствии заголовка, соответствующего name; по умолчанию он равен None. Это предпочтительный способ получения разобранных заголовков.

Message.get(name[, default])

Псевдоним для getheader(), чтобы сделать интерфейс более совместимым с обычными словарями.

Message.getaddr(name)

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

Пример: если первый заголовок From объекта m содержит строку 'jack@cwi.nl (Jack Jansen)', то m.getaddr('From') вернёт пару ('Jack Jansen', 'jack@cwi.nl'). Если бы заголовок содержал 'Jack Jansen <jack@cwi.nl>', результат был бы точно таким же.

Message.getaddrlist(name)

Это похоже на getaddr(list), но разбирает заголовок, содержащий список адресов электронной почты (например, заголовок To), и возвращает список пар (full name, email address) (даже если в заголовке был только один адрес). Если заголовок, соответствующий name, отсутствует, возвращает пустой список.

Если существует несколько заголовков, соответствующих указанному имени (например, несколько заголовков Cc), все они разбираются на адреса. Также разбираются все строки продолжения, содержащиеся в этих заголовках.

Message.getdate(name)

Извлекает заголовок с помощью getheader() и разбирает его в 9-кортеж, совместимый с time.mktime(); обратите внимание, что поля 6, 7 и 8 непригодны. Если заголовок, соответствующий name, отсутствует или не поддаётся разбору, возвращает None.

Разбор даты – это, похоже, чёрная магия, и не все почтовые программы следуют стандарту. Хотя функция была протестирована и признана корректной на большой коллекции писем из многих источников, всё же возможно, что иногда она будет выдавать неверный результат.

Message.getdate_tz(name)

Извлекает заголовок с помощью getheader() и разбирает его в 10-кортеж; первые 9 элементов образуют кортеж, совместимый с time.mktime(), а 10-й – число, указывающее смещение часового пояса даты от UTC. Обратите внимание, что поля 6, 7 и 8 непригодны. Как и в getdate(), если заголовок, соответствующий name, отсутствует или не поддаётся разбору, возвращает None.

Экземпляры Message также поддерживают ограниченный интерфейс отображения. В частности: m[name] работает как m.getheader(name), но вызывает KeyError, если нет соответствующего заголовка; а len(m), m.get(name[, default]), name in m, m.keys(), m.values() m.items() и m.setdefault(name[, default]) ведут себя как ожидается, с одной разницей: setdefault() использует пустую строку в качестве значения по умолчанию. Экземпляры Message также поддерживают интерфейс записи отображения m[name] = value и del m[name]. Объекты Message не поддерживают методы clear(), copy(), popitem() или update() интерфейса отображения. (Поддержка get() и setdefault() была добавлена только в Python 2.2.)

Наконец, экземпляры Message имеют несколько открытых переменных экземпляра:

Message.headers

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

Message.fp

Файл или файлоподобный объект, переданный при создании экземпляра. Может использоваться для чтения содержимого сообщения.

Message.unixfrom

Строка Unix From, если она присутствует в сообщении, или пустая строка. Это необходимо для регенерации сообщения в некоторых контекстах, например, в почтовом файле стиля mbox.

18.11.2. Объекты AddressListAddressList Objects

Экземпляр AddressList имеет следующие методы:

AddressList.__len__()

Возвращает количество адресов в списке адресов.

AddressList.__str__()

Возвращает каноническое строковое представление списка адресов. Адреса отображаются в форме «имя» <host@domain>, разделённые запятыми.

AddressList.__add__(alist)

Возвращает новый экземпляр AddressList, содержащий все адреса из обоих операндов AddressList, с удалением дубликатов (объединение множеств).

AddressList.__iadd__(alist)

Версия __add__(), изменяющая объект на месте; превращает данный экземпляр AddressList в объединение самого себя и правого экземпляра alist.

AddressList.__sub__(alist)

Возвращает новый экземпляр AddressList, содержащий все адреса из левого операнда AddressList, которые отсутствуют в правом операнде (разность множеств).

AddressList.__isub__(alist)

Версия __sub__(), изменяющая объект на месте; удаляет из этого списка адреса, которые также присутствуют в alist.

Наконец, экземпляры AddressList имеют одну открытую переменную экземпляра:

AddressList.addresslist

Список кортежей из двух строк, по одному на каждый адрес. В каждом элементе первый – каноническая часть имени, второй – фактический маршрутный адрес (пара «имя пользователя»-«хост.домен», разделённая '@').

Сноски

1

Этот модуль изначально соответствовал RFC 822, отсюда и название. С тех пор RFC 2822 был выпущен как обновление RFC 822. Этот модуль следует считать RFC 2822-совместимым, особенно в случаях, когда синтаксис или семантика изменились после RFC 822.