> **Источник:** https://python-all.ru/2.7/library/rfc822.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 18.11. [`rfc822`](https://python-all.ru/2.7/library/rfc822.html#module-rfc822) – Разбор заголовков почты RFC 2822

Устарело с версии 2.3: Пакет [`email`](https://python-all.ru/2.7/library/email.html#module-email) следует использовать вместо модуля [`rfc822`](https://python-all.ru/2.7/library/rfc822.html#module-rfc822). Этот модуль существует только для поддержки обратной совместимости и удалён в Python 3.

Этот модуль определяет класс [`Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message), который представляет «сообщение электронной почты», как определено в интернет-стандарте [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html). [1](https://python-all.ru/2.7/library/rfc822.html#id4) Такие сообщения состоят из набора заголовков и тела сообщения. В этом модуле также определён вспомогательный класс [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList) для разбора адресов [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html). Обратитесь к RFC за информацией о конкретном синтаксисе сообщений [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html).

Модуль [`mailbox`](https://python-all.ru/2.7/library/mailbox.html#module-mailbox) предоставляет классы для чтения почтовых ящиков, созданных различными пользовательскими почтовыми программами.

#### `class rfc822.Message(file[, seekable])`

Экземпляр [`Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message) создаётся с входным объектом в качестве параметра. Message полагается только на то, что входной объект имеет метод [`readline()`](https://python-all.ru/2.7/library/readline.html#module-readline); в частности, подходят обычные файловые объекты. При создании экземпляра заголовки читаются из входного объекта до строки-разделителя (обычно пустой строки) и сохраняются в экземпляре. Тело сообщения, следующее за заголовками, не потребляется.

Этот класс может работать с любым входным объектом, поддерживающим метод [`readline()`](https://python-all.ru/2.7/library/readline.html#module-readline). Если входной объект имеет возможность seek и tell, будет работать метод [`rewindbody()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message.rewindbody); кроме того, некорректные строки будут возвращены обратно во входной поток. Если входной объект не имеет seek, но имеет метод `unread()`, который может вернуть строку обратно, [`Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message) будет использовать его для возврата некорректных строк. Таким образом, этот класс можно использовать для разбора сообщений, поступающих из буферизованного потока.

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

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

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

#### `class rfc822.AddressList(field)`

Можно создать экземпляр вспомогательного класса [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList), используя один строковый параметр – список адресов [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html), разделённых запятыми, для разбора. (Параметр `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()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.parseaddr), она принимает кортеж из двух элементов вида `(realname, email_address)` и возвращает строковое значение, подходящее для заголовка *To* или *Cc*. Если первый элемент *pair* равен false, то второй элемент возвращается без изменений.

#### `rfc822.parsedate(date)`

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

#### `rfc822.parsedate_tz(date)`

Выполняет ту же функцию, что и [`parsedate()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.parsedate), но возвращает либо `None`, либо кортеж из 10 элементов; первые 9 элементов образуют кортеж, который можно напрямую передать в [`time.mktime()`](https://python-all.ru/2.7/library/time.html#time.mktime), а десятый – смещение часового пояса даты относительно UTC (официальный термин для среднего времени по Гринвичу). (Обратите внимание, что знак смещения часового пояса противоположен знаку переменной `time.timezone` для того же часового пояса; последняя переменная соответствует стандарту POSIX, тогда как этот модуль следует [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html).) Если входная строка не содержит часового пояса, последним элементом возвращаемого кортежа является `None`. Обратите внимание, что индексы 6, 7 и 8 результирующего кортежа не могут быть использованы.

#### `rfc822.mktime_tz(tuple)`

Преобразует кортеж из 10 элементов, возвращаемый функцией [`parsedate_tz()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.parsedate_tz), во временную метку UTC. Если элемент часового пояса в кортеже равен `None`, предполагается местное время. Небольшой недостаток: сначала первые 8 элементов интерпретируются как местное время, а затем применяется поправка на разницу часовых поясов; это может привести к небольшой ошибке в даты перехода на летнее время. Но для обычного использования это несущественно.

> **См. также**
>
> **Модуль [`email`](https://python-all.ru/2.7/library/email.html#module-email)**
>
> Комплексный пакет для обработки электронной почты; заменяет модуль [`rfc822`](https://python-all.ru/2.7/library/rfc822.html#module-rfc822).
>
> **Модуль [`mailbox`](https://python-all.ru/2.7/library/mailbox.html#module-mailbox)**
>
> Классы для чтения различных форматов почтовых ящиков, созданных пользовательскими почтовыми программами.
>
> **Модуль [`mimetools`](https://python-all.ru/2.7/library/mimetools.html#module-mimetools)**
>
> Подкласс [`rfc822.Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message), обрабатывающий сообщения в кодировке MIME.

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

Экземпляр [`Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message) имеет следующие методы:

#### `Message.rewindbody()`

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

#### `Message.isheader(line)`

Возвращает канонизированное имя поля строки (ключ словаря, который будет использоваться для индексации), если строка является допустимым заголовком [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html); в противном случае возвращает `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()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message.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()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message.getheader) и разбирает его в 9-кортеж, совместимый с [`time.mktime()`](https://python-all.ru/2.7/library/time.html#time.mktime); обратите внимание, что поля 6, 7 и 8 непригодны. Если заголовок, соответствующий *name*, отсутствует или не поддаётся разбору, возвращает `None`.

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

#### `Message.getdate_tz(name)`

Извлекает заголовок с помощью [`getheader()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message.getheader) и разбирает его в 10-кортеж; первые 9 элементов образуют кортеж, совместимый с [`time.mktime()`](https://python-all.ru/2.7/library/time.html#time.mktime), а 10-й – число, указывающее смещение часового пояса даты от UTC. Обратите внимание, что поля 6, 7 и 8 непригодны. Как и в [`getdate()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message.getdate), если заголовок, соответствующий *name*, отсутствует или не поддаётся разбору, возвращает `None`.

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

Наконец, экземпляры [`Message`](https://python-all.ru/2.7/library/rfc822.html#rfc822.Message) имеют несколько открытых переменных экземпляра:

#### `Message.headers`

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

#### `Message.fp`

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

#### `Message.unixfrom`

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

## 18.11.2. Объекты AddressList

Экземпляр [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList) имеет следующие методы:

#### `AddressList.__len__()`

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

#### `AddressList.__str__()`

Возвращает каноническое строковое представление списка адресов. Адреса отображаются в форме «имя» \<[host@domain](https://python-all.ru/2.7/library/rfc822.html)\>, разделённые запятыми.

#### `AddressList.__add__(alist)`

Возвращает новый экземпляр [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList), содержащий все адреса из обоих операндов [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList), с удалением дубликатов (объединение множеств).

#### `AddressList.__iadd__(alist)`

Версия [`__add__()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList.__add__), изменяющая объект на месте; превращает данный экземпляр [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList) в объединение самого себя и правого экземпляра *alist*.

#### `AddressList.__sub__(alist)`

Возвращает новый экземпляр [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList), содержащий все адреса из левого операнда [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList), которые отсутствуют в правом операнде (разность множеств).

#### `AddressList.__isub__(alist)`

Версия [`__sub__()`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList.__sub__), изменяющая объект на месте; удаляет из этого списка адреса, которые также присутствуют в *alist*.

Наконец, экземпляры [`AddressList`](https://python-all.ru/2.7/library/rfc822.html#rfc822.AddressList) имеют одну открытую переменную экземпляра:

#### `AddressList.addresslist`

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

Сноски

**[1](https://python-all.ru/2.7/library/rfc822.html#id1)**

Этот модуль изначально соответствовал [**RFC 822**](https://python-all.ru/2.7/library/rfc822.html), отсюда и название. С тех пор [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html) был выпущен как обновление [**RFC 822**](https://python-all.ru/2.7/library/rfc822.html). Этот модуль следует считать [**RFC 2822**](https://python-all.ru/2.7/library/rfc822.html)-совместимым, особенно в случаях, когда синтаксис или семантика изменились после [**RFC 822**](https://python-all.ru/2.7/library/rfc822.html).
