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

---

# 18.4. `mailbox` – Работа с почтовыми ящиками в различных форматах

Этот модуль определяет два класса: [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) и [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), для доступа к почтовым ящикам на диске и содержащимся в них сообщениям и управления ими. [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) предоставляет отображение в стиле словаря, связывающее ключи с сообщениями. [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message) расширяет класс `email.Message` модуля [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), добавляя состояние и поведение, зависящие от формата. Поддерживаемые форматы почтовых ящиков: Maildir, mbox, MH, Babyl и MMDF.

> **См. также**
>
> **Модуль [`email`](https://python-all.ru/3.1/library/email.html#module-email)**
>
> Представление сообщений и управление ими.

## 18.4.1. [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) объекты

#### `class mailbox.Mailbox`

Почтовый ящик, который можно просматривать и изменять.

Класс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) определяет интерфейс и не предназначен для создания экземпляров. Вместо этого от [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) должны наследоваться подклассы, специфичные для формата, а код должен создавать экземпляры конкретного подкласса.

Интерфейс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) напоминает словарь: небольшие ключи соответствуют сообщениям. Ключи выдаются экземпляром [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), с которым они будут использоваться, и имеют смысл только для этого экземпляра [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox). Ключ продолжает идентифицировать сообщение, даже если соответствующее сообщение изменяется, например, заменяется другим сообщением.

Сообщения можно добавлять в экземпляр [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) с помощью метода, подобного set, [`add()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.add), и удалять с помощью инструкции `del` или методов, подобных set, [`remove()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.remove) и [`discard()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.discard).

Семантика интерфейса [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) отличается от семантики словаря в некоторых важных аспектах. При каждом запросе сообщения создаётся новое представление (обычно экземпляр [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)) на основе текущего состояния почтового ящика. Аналогично, при добавлении сообщения в экземпляр [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) содержимое переданного представления сообщения копируется. Ни в одном из случаев экземпляр [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) не хранит ссылку на представление сообщения.

Итератор по умолчанию [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) перебирает представления сообщений, а не ключи, как это делает итератор словаря по умолчанию. Более того, изменение почтового ящика во время итерации безопасно и имеет чётко определённое поведение. Сообщения, добавленные в почтовый ящик после создания итератора, не будут видны итератору. Сообщения, удалённые из почтового ящика до того, как итератор вернёт их, будут молча пропущены, хотя использование ключа от итератора может привести к исключению [`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError), если соответствующее сообщение будет впоследствии удалено.

> **Предупреждение**
>
> Следует соблюдать осторожность при изменении почтовых ящиков, которые могут одновременно изменяться другим процессом. Самый безопасный формат почтового ящика для таких задач – Maildir; следует избегать использования однофайловых форматов, таких как mbox, для одновременной записи. При изменении почтового ящика *необходимо* заблокировать его, вызвав методы [`lock()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.lock) и [`unlock()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.unlock) *перед* чтением любых сообщений в файле или внесением любых изменений путём добавления или удаления сообщения. Неблокировка почтового ящика может привести к потере сообщений или повреждению всего почтового ящика.

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

#### `add(message)`

Добавляет *сообщение* в почтовый ящик и возвращает ключ, который был ему присвоен.

Параметр *message* может быть экземпляром [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), экземпляром `email.Message.Message`, строкой или файлоподобным объектом (который должен быть открыт в текстовом режиме). Если *message* является экземпляром соответствующего подкласса [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), специфичного для формата (например, если это экземпляр [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage), а текущий объект – экземпляр [`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox)), то используется информация, специфичная для формата. В противном случае используются разумные значения по умолчанию.

#### `remove(key)`

#### `__delitem__(key)`

#### `discard(key)`

Удаляет сообщение, соответствующее *ключу*, из почтового ящика.

Если такого сообщения не существует, исключение [`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError) возбуждается, если метод был вызван как [`remove()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.remove) или [`__delitem__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__delitem__), но исключение не возбуждается, если метод был вызван как [`discard()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.discard). Поведение [`discard()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.discard) может быть предпочтительнее, если базовый формат почтового ящика поддерживает одновременное изменение другими процессами.

#### `__setitem__(key, message)`

Заменяет сообщение, соответствующее *key*, на *message*. Возбуждает исключение [`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError), если сообщение, соответствующее *key*, ещё не существует.

Как и для [`add()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.add), параметр *message* может быть экземпляром [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), экземпляром `email.Message.Message`, строкой или файлоподобным объектом (открытым в текстовом режиме). Если *message* является экземпляром соответствующего подкласса [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), специфичного для формата (например, если это экземпляр [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage), а текущий объект – экземпляр [`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox)), то используется информация, специфичная для формата. В противном случае информация, специфичная для формата сообщения, соответствующего ключу *key*, остаётся без изменений.

#### `iterkeys()`

#### `keys()`

Возвращает итератор по всем ключам, если вызван как

[`iterkeys()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.iterkeys)

, или возвращает список ключей, если вызван как

[`keys()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.keys)

.

#### `itervalues()`

#### `__iter__()`

#### `values()`

Возвращает итератор по представлениям всех сообщений, если вызван как [`itervalues()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.itervalues) или [`__iter__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__iter__), или возвращает список таких представлений, если вызван как [`values()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.values). Сообщения представляются как экземпляры соответствующего формат-специфичного подкласса [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), если только при инициализации экземпляра [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) не была указана пользовательская фабрика сообщений.

> **Примечание**
>
> Поведение [`__iter__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__iter__) отличается от поведения словарей, которые перебирают ключи.

#### `iteritems()`

#### `items()`

Возвращает итератор по парам (

*ключ*

,

*сообщение*

), где

*ключ*

– это ключ, а

*сообщение*

– представление сообщения, если метод вызван как

[`iteritems()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.iteritems)

, или возвращает список таких пар, если вызван как

[`items()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.items)

. Сообщения представляются как экземпляры соответствующего подкласса

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, зависящего от формата, если только при инициализации экземпляра

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

не была указана пользовательская фабрика сообщений.

#### `get(key, default=None)`

#### `__getitem__(key)`

Возвращает представление сообщения, соответствующего

*ключу*

. Если такое сообщение отсутствует, возвращается

*значение по умолчанию*

, если метод был вызван как

[`get()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.get)

, и возбуждается исключение

[`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError)

, если метод был вызван как

[`__getitem__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__getitem__)

. Сообщение представляется как экземпляр соответствующего подкласса

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, зависящего от формата, если только при инициализации экземпляра

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

не была указана пользовательская фабрика сообщений.

#### `get_message(key)`

Возвращает представление сообщения, соответствующего

*ключу*

, в виде экземпляра соответствующего подкласса

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, зависящего от формата, или возбуждает исключение

[`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError)

, если такое сообщение отсутствует.

#### `get_string(key)`

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

*key*

, или возбуждает исключение

[`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError)

, если такого сообщения нет.

#### `get_file(key)`

Возвращает файлоподобное представление сообщения, соответствующего ключу *key*, или возбуждает исключение [`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError), если такого сообщения нет. Файлоподобный объект ведёт себя так, как если бы он был открыт в двоичном режиме. Этот файл следует закрыть, когда он больше не нужен.

> **Примечание**
>
> В отличие от других представлений сообщений, файлоподобные представления не обязательно независимы от экземпляра [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), создавшего их, или от базового почтового ящика. Более подробная документация приведена в каждом подклассе.

#### `__contains__(key)`

Возвращает

`True`

, если

*ключ*

соответствует сообщению, и

`False`

в противном случае.

#### `__len__()`

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

#### `clear()`

Удаляет все сообщения из почтового ящика.

#### `pop(key, default=None)`

Возвращает представление сообщения, соответствующего

*ключу*

, и удаляет сообщение. Если такое сообщение отсутствует, возвращает

*значение по умолчанию*

. Сообщение представляется как экземпляр соответствующего подкласса

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, зависящего от формата, если только при инициализации экземпляра

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

не была указана пользовательская фабрика сообщений.

#### `popitem()`

Возвращает произвольную пару (

*ключ*

,

*сообщение*

), где

*ключ*

– это ключ, а

*сообщение*

– представление сообщения, и удаляет соответствующее сообщение. Если почтовый ящик пуст, возбуждает исключение

[`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError)

. Сообщение представляется как экземпляр соответствующего подкласса

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, зависящего от формата, если только при инициализации экземпляра

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

не была указана пользовательская фабрика сообщений.

#### `update(arg)`

Параметр *arg* должен быть отображением *ключ* → *сообщение* или итерируемым объектом из пар (*ключ*, *сообщение*). Обновляет почтовый ящик так, что для каждого заданного *ключа* и *сообщения* сообщение, соответствующее *ключу*, устанавливается в *сообщение*, как если бы это было сделано с помощью [`__setitem__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__setitem__). Как и в случае с [`__setitem__()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.__setitem__), каждый *ключ* уже должен соответствовать сообщению в почтовом ящике, иначе будет возбуждено исключение [`KeyError`](https://python-all.ru/3.1/library/exceptions.html#KeyError), поэтому в общем случае неверно, чтобы *arg* был экземпляром [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox).

> **Примечание**
>
> В отличие от словарей, именованные аргументы не поддерживаются.

#### `flush()`

Записывает все ожидающие изменения в файловую систему. Для некоторых подклассов

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

изменения всегда записываются немедленно, и

[`flush()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox.flush)

ничего не делает, но всё равно стоит выработать привычку вызывать этот метод.

#### `lock()`

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

[`ExternalClashError`](https://python-all.ru/3.1/library/mailbox.html#mailbox.ExternalClashError)

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

*всегда*

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

#### `unlock()`

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

#### `close()`

Сбрасывает почтовый ящик, разблокирует его при необходимости и закрывает все открытые файлы. Для некоторых подклассов

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

этот метод ничего не делает.

### 18.4.1.1. [`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir)

#### `class mailbox.Maildir(dirname, factory=None, create=True)`

Подкласс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) для почтовых ящиков в формате Maildir. Параметр *factory* – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя как открытое в двоичном режиме) и возвращает пользовательское представление. Если *factory* равно `None`, то [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) используется как представление сообщения по умолчанию. Если *create* равно `True`, почтовый ящик создаётся, если он не существует.

По историческим причинам *dirname* назван так, а не *path*.

Maildir – это почтовый формат на основе каталогов, разработанный для агента передачи почты qmail и ныне широко поддерживаемый другими программами. Сообщения в почтовом ящике Maildir хранятся в отдельных файлах в общей структуре каталогов. Такая архитектура позволяет нескольким независимым программам получать доступ и изменять почтовые ящики Maildir без повреждения данных, поэтому файловая блокировка не требуется.

Почтовые ящики Maildir содержат три подкаталога: `tmp`, `new` и `cur`. Сообщения сперва создаются в подкаталоге `tmp`, а затем перемещаются в подкаталог `new` для завершения доставки. Почтовый клиент может затем переместить сообщение в подкаталог `cur` и сохранить информацию о состоянии сообщения в специальном разделе «info», добавляемом к его имени файла.

Также поддерживаются папки в стиле, введённом почтовым транспортным агентом Courier. Любой подкаталог основного почтового ящика считается папкой, если `'.'` является первым символом в его имени. Имена папок представляются объектами [`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir) без ведущего `'.'`. Каждая папка сама является почтовым ящиком Maildir, но не должна содержать другие папки. Вместо этого логическая вложенность указывается с помощью `'.'` для разделения уровней, например «Archived.2005.07».

> **Примечание**
>
> Спецификация Maildir требует использования двоеточия (`':'`) в некоторых именах файлов сообщений. Однако некоторые операционные системы не допускают этот символ в именах файлов. Если вы хотите использовать формат, подобный Maildir, в такой операционной системе, следует указать другой символ для замены. Восклицательный знак (`'!'`) – популярный выбор. Например:
>
> ```python
> import mailbox
> mailbox.Maildir.colon = '!'
> ```
>
> Атрибут `colon` также может быть установлен для каждого экземпляра отдельно.

Экземпляры [`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir) обладают всеми методами [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), а также следующими:

#### `list_folders()`

Возвращает список имён всех папок.

#### `get_folder(folder)`

Возвращает экземпляр

[`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir)

, представляющий папку с именем

*folder*

. Если папка не существует, возбуждается исключение

[`NoSuchMailboxError`](https://python-all.ru/3.1/library/mailbox.html#mailbox.NoSuchMailboxError)

.

#### `add_folder(folder)`

Создаёт папку с именем

*folder*

и возвращает экземпляр

[`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir)

, представляющий её.

#### `remove_folder(folder)`

Удаляет папку с именем

*folder*

. Если папка содержит какие-либо сообщения, будет выброшено исключение

[`NotEmptyError`](https://python-all.ru/3.1/library/mailbox.html#mailbox.NotEmptyError)

, и папка не будет удалена.

#### `clean()`

Удаляет временные файлы из почтового ящика, к которым не было обращений за последние 36 часов. Спецификация Maildir утверждает, что программы чтения почты должны делать это время от времени.

Некоторые методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), реализованные в [`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir), заслуживают особых замечаний:

#### `add(message)`

#### `__setitem__(key, message)`

#### `update(arg)`

> **Предупреждение**
>
> Эти методы генерируют уникальные имена файлов на основе идентификатора текущего процесса. При использовании нескольких потоков возможны незамеченные конфликты имен, которые могут привести к повреждению почтового ящика, если потоки не скоординированы, чтобы избежать одновременного использования этих методов для управления одним и тем же почтовым ящиком.

#### `flush()`

Все изменения в почтовых ящиках Maildir применяются немедленно, поэтому этот метод ничего не делает.

#### `lock()`

#### `unlock()`

Почтовые ящики Maildir не поддерживают (и не требуют) блокировку, поэтому эти методы ничего не делают.

#### `close()`

Экземпляры

[`Maildir`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Maildir)

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

#### `get_file(key)`

В зависимости от платформы может быть невозможно изменить или удалить нижележащее сообщение, пока возвращенный файл остается открытым.

> **См. также**
>
> **[Страница руководства maildir из qmail](https://python-all.ru/3.1/library/mailbox.html)**
>
> Оригинальная спецификация формата.
>
> **[Использование формата maildir](https://python-all.ru/3.1/library/mailbox.html)**
>
> Заметки о Maildir от его создателя. Включают обновлённую схему создания имён и детали семантики «info».
>
> **[man-страница maildir из Courier](https://python-all.ru/3.1/library/mailbox.html)**
>
> Другая спецификация формата. Описывает распространённое расширение для поддержки папок.

### 18.4.1.2. [`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox)

#### `class mailbox.mbox(path, factory=None, create=True)`

Подкласс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) для почтовых ящиков в формате mbox. Параметр *factory* – это вызываемый объект, который принимает файлоподобное представление сообщения (которое ведёт себя как открытое в двоичном режиме) и возвращает пользовательское представление. Если *factory* равно `None`, то [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) используется как представление сообщения по умолчанию. Если *create* равно `True`, почтовый ящик создаётся, если он не существует.

Формат mbox – это классический формат хранения почты в системах Unix. Все сообщения в почтовом ящике mbox хранятся в одном файле, при этом начало каждого сообщения обозначается строкой, первые пять символов которой – «From ».

Существует несколько вариантов формата mbox, призванных устранить предполагаемые недостатки оригинала. Ради совместимости [`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox) реализует оригинальный формат, который иногда называют *mboxo*. Это означает, что заголовок *Content-Length*, если он присутствует, игнорируется, а любые вхождения «From » в начале строки тела сообщения преобразуются в «\>From » при сохранении сообщения, хотя вхождения «\>From » не преобразуются обратно в «From » при чтении сообщения.

Некоторые методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), реализованные в [`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox), заслуживают особых замечаний:

#### `get_file(key)`

Использование файла после вызова

`flush()`

или

`close()`

на экземпляре

[`mbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mbox)

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

#### `lock()`

#### `unlock()`

Используются три механизма блокировки: точечная блокировка и, если доступны, системные вызовы

`flock()`

и

`lockf()`

.

> **См. также**
>
> **[Страница руководства mbox из qmail](https://python-all.ru/3.1/library/mailbox.html)**
>
> Спецификация формата и его разновидностей.
>
> **[Страница man mbox из tin](https://python-all.ru/3.1/library/mailbox.html)**
>
> Другая спецификация формата, с подробностями о блокировке.
>
> **[Настройка Netscape Mail в Unix: почему формат Content-Length плох](https://python-all.ru/3.1/library/mailbox.html)**
>
> Аргумент в пользу использования оригинального формата mbox, а не его вариации.
>
> **[«mbox» – это семейство нескольких взаимно несовместимых форматов почтовых ящиков](https://python-all.ru/3.1/library/mailbox.html)**
>
> История вариаций mbox.

### 18.4.1.3. [`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH)

#### `class mailbox.MH(path, factory=None, create=True)`

Подкласс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) для почтовых ящиков в формате MH. Параметр *factory* – это вызываемый объект, который принимает файлоподобное представление сообщения (которое ведёт себя так, как если бы было открыто в двоичном режиме) и возвращает пользовательское представление. Если *factory* равно `None`, в качестве представления сообщения по умолчанию используется [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage). Если *create* равно `True`, почтовый ящик создаётся, если он не существует.

MH – это формат почтового ящика, основанный на каталогах, разработанный для системы обработки сообщений MH (почтового клиента). Каждое сообщение в почтовом ящике MH находится в собственном файле. Почтовый ящик MH может содержать другие почтовые ящики MH (называемые *папками*) в дополнение к сообщениям. Папки могут быть вложены неограниченно. Почтовые ящики MH также поддерживают *последовательности*, которые представляют собой именованные списки, используемые для логической группировки сообщений без перемещения их в подпапки. Последовательности определяются в файле `.mh_sequences` в каждой папке.

Класс [`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH) управляет почтовыми ящиками MH, но не пытается эмулировать все поведения **mh**. В частности, он не изменяет и не зависит от файлов `context` или `.mh_profile`, которые используются **mh** для хранения своего состояния и конфигурации.

Экземпляры [`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH) имеют все методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) в дополнение к следующим:

#### `list_folders()`

Возвращает список имён всех папок.

#### `get_folder(folder)`

Возвращает экземпляр

[`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH)

, представляющий папку с именем

*folder*

. Исключение

[`NoSuchMailboxError`](https://python-all.ru/3.1/library/mailbox.html#mailbox.NoSuchMailboxError)

выбрасывается, если папка не существует.

#### `add_folder(folder)`

Создаёт папку с именем

*folder*

и возвращает экземпляр

[`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH)

, представляющий её.

#### `remove_folder(folder)`

Удаляет папку с именем

*folder*

. Если папка содержит какие-либо сообщения, будет выброшено исключение

[`NotEmptyError`](https://python-all.ru/3.1/library/mailbox.html#mailbox.NotEmptyError)

, и папка не будет удалена.

#### `get_sequences()`

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

#### `set_sequences(sequences)`

Переопределяет последовательности, существующие в почтовом ящике, на основе

*sequences*

, словаря имён, сопоставленных со списками ключей, как возвращаемый

[`get_sequences()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH.get_sequences)

.

#### `pack()`

Переименовывает сообщения в почтовом ящике по мере необходимости для устранения пропусков в нумерации. Записи в списке последовательностей обновляются соответствующим образом.

> **Примечание**
>
> Ранее выданные ключи становятся недействительными в результате этой операции и не должны использоваться в дальнейшем.

Некоторые методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), реализованные в [`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH), заслуживают особых замечаний:

#### `remove(key)`

#### `__delitem__(key)`

#### `discard(key)`

Эти методы немедленно удаляют сообщение. Соглашение MH помечать сообщение на удаление добавлением запятой к его имени не используется.

#### `lock()`

#### `unlock()`

Используются три механизма блокировки – dot-блокировка и, если доступны,

`flock()`

и

`lockf()`

системные вызовы. Для почтовых ящиков MH блокировка почтового ящика означает блокировку файла

`.mh_sequences`

и, только на время любых операций, которые на них влияют, блокировку отдельных файлов сообщений.

#### `get_file(key)`

В зависимости от платформы может быть невозможно удалить базовое сообщение, пока возвращённый файл остаётся открытым.

#### `flush()`

Все изменения в почтовых ящиках MH применяются немедленно, поэтому этот метод ничего не делает.

#### `close()`

Экземпляры

[`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH)

не хранят открытых файлов, поэтому этот метод эквивалентен

[`unlock()`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH.unlock)

.

> **См. также**
>
> **[nmh – система обработки сообщений](https://python-all.ru/3.1/library/mailbox.html)**
>
> Домашняя страница
>
> **nmh**
>
> , обновлённой версии исходного
>
> **mh**
>
> .
>
> **[MH и nmh: электронная почта для пользователей и программистов](https://python-all.ru/3.1/library/mailbox.html)**
>
> Книга, лицензированная под GPL, о
>
> **mh**
>
> и
>
> **nmh**
>
> , с некоторой информацией о формате почтового ящика.

### 18.4.1.4. [`Babyl`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Babyl)

#### `class mailbox.Babyl(path, factory=None, create=True)`

Подкласс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) для почтовых ящиков в формате Babyl. Параметр *factory* – это вызываемый объект, который принимает файлоподобное представление сообщения (которое ведет себя так, как если бы было открыто в бинарном режиме) и возвращает пользовательское представление. Если *factory* равно `None`, то в качестве представления сообщения по умолчанию используется [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage). Если *create* равно `True`, почтовый ящик создается, если он не существует.

Babyl – это однофайловый формат почтового ящика, используемый почтовым клиентом Rmail, входящим в состав Emacs. Начало сообщения обозначается строкой, содержащей два символа: Control-Подчёркивание (`'\037'`) и Control-L (`'\014'`). Конец сообщения обозначается началом следующего сообщения или, в случае последнего сообщения, строкой, содержащей символ Control-Подчёркивание (`'\037'`).

Сообщения в почтовом ящике Babyl имеют два набора заголовков: исходные заголовки и так называемые видимые заголовки. Видимые заголовки обычно являются подмножеством исходных заголовков, которые были переформатированы или сокращены для большей привлекательности. Каждое сообщение в почтовом ящике Babyl также имеет сопутствующий список *меток* (коротких строк, которые записывают дополнительную информацию о сообщении), а список всех определённых пользователем меток, найденных в почтовом ящике, хранится в разделе параметров Babyl.

Экземпляры [`Babyl`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Babyl) имеют все методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), а также следующие:

#### `get_labels()`

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

> **Примечание**
>
> Фактические сообщения проверяются для определения того, какие метки существуют в почтовом ящике, вместо обращения к списку меток в разделе параметров Babyl, но раздел Babyl обновляется при каждом изменении почтового ящика.

Некоторые методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), реализованные в [`Babyl`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Babyl), заслуживают отдельных замечаний:

#### `get_file(key)`

В почтовых ящиках Babyl заголовки сообщения хранятся не последовательно с телом сообщения. Чтобы создать файлоподобное представление, заголовки и тело копируются вместе в экземпляр

`StringIO`

(из модуля

`StringIO`

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

#### `lock()`

#### `unlock()`

Используются три механизма блокировки: точечная блокировка и, если доступны, системные вызовы

`flock()`

и

`lockf()`

.

> **См. также**
>
> **[Формат файлов Babyl версии 5](https://python-all.ru/3.1/library/mailbox.html)**
>
> Спецификация формата Babyl.
>
> **[Чтение почты с помощью Rmail](https://python-all.ru/3.1/library/mailbox.html)**
>
> Руководство по Rmail, содержащее некоторую информацию о семантике Babyl.

### 18.4.1.5. [`MMDF`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDF)

#### `class mailbox.MMDF(path, factory=None, create=True)`

Подкласс [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) для почтовых ящиков в формате MMDF. Параметр *factory* – это вызываемый объект, который принимает файлоподобное представление сообщения (которое ведет себя так, как если бы было открыто в бинарном режиме) и возвращает пользовательское представление. Если *factory* равно `None`, то в качестве представления сообщения по умолчанию используется [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage). Если *create* равно `True`, почтовый ящик создается, если он не существует.

MMDF – это однофайловый формат почтового ящика, разработанный для Multichannel Memorandum Distribution Facility – агента пересылки почты. Каждое сообщение имеет ту же форму, что и сообщение mbox, но обрамляется строками, содержащими четыре символа Control-A (`'\001'`). Как и в формате mbox, начало каждого сообщения обозначается строкой, первые пять символов которой – «From », но дополнительные вхождения «From » не преобразуются в «\>From » при сохранении сообщений, так как дополнительные строки-разделители сообщений предотвращают ошибочный прием таких вхождений за начала последующих сообщений.

Некоторые методы [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox), реализованные в [`MMDF`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDF), заслуживают отдельных замечаний:

#### `get_file(key)`

Использование файла после вызова

`flush()`

или

`close()`

на экземпляре

[`MMDF`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDF)

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

#### `lock()`

#### `unlock()`

Используются три механизма блокировки: точечная блокировка и, если доступны, системные вызовы

`flock()`

и

`lockf()`

.

> **См. также**
>
> **[страница руководства mmdf из tin](https://python-all.ru/3.1/library/mailbox.html)**
>
> Спецификация формата MMDF из документации tin, программы для чтения новостей.
>
> **[MMDF](https://python-all.ru/3.1/library/mailbox.html)**
>
> Статья в Википедии, описывающая Multichannel Memorandum Distribution Facility.

## 18.4.2. объекты [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

#### `class mailbox.Message(message=None)`

Подкласс `email.Message` модуля [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message). Подклассы [`mailbox.Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message) добавляют состояние и поведение, специфичные для формата почтового ящика.

Если *message* опущен, новый экземпляр создаётся в состоянии по умолчанию, пустом. Если *message* является экземпляром `email.Message.Message`, его содержимое копируется; кроме того, любая информация, специфичная для формата, по возможности преобразуется, если *message* является экземпляром [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message). Если *message* является строкой или файлом, он должен содержать сообщение, соответствующее [**RFC 2822**](https://python-all.ru/3.1/library/mailbox.html), которое читается и разбирается.

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

Нет требования, чтобы экземпляры [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message) использовались для представления сообщений, полученных с помощью экземпляров [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox). В некоторых ситуациях время и память, необходимые для создания представлений [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message), могут оказаться неприемлемыми. Для таких ситуаций экземпляры [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox) также предоставляют строковые и файлоподобные представления, а также может быть указана пользовательская фабрика сообщений при инициализации экземпляра [`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox).

### 18.4.2.1. [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage)

#### `class mailbox.MaildirMessage(message=None)`

Сообщение с поведением, специфичным для Maildir. Параметр *message* имеет то же значение, что и в конструкторе [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message).

Обычно почтовый клиент перемещает все сообщения из подкаталога `new` в подкаталог `cur` после первого открытия и закрытия почтового ящика пользователем, отмечая, что сообщения устарели, независимо от того, были ли они прочитаны. Каждое сообщение в `cur` имеет раздел «info», добавленный к его имени файла, для хранения информации о его состоянии. (Некоторые почтовые программы могут также добавлять раздел «info» к сообщениям в `new`.) Раздел «info» может принимать одну из двух форм: он может содержать «2,» с последующим списком стандартизированных флагов (например, «2,FR») или может содержать «1,» с последующей так называемой экспериментальной информацией. Стандартные флаги для сообщений Maildir следующие:

| Флаг | Значение | Пояснение |
| --- | --- | --- |
| D | Черновик | В процессе составления |
| F | Помечено | Помечено как важное |
| P | Передан | Переслано, отправлено повторно или возвращено |
| R | Отвечено | Получен ответ |
| S | Просмотрено | Прочитано |
| T | Удалено | Помечено для последующего удаления |

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

#### `get_subdir()`

Возвращает либо «new» (если сообщение должно храниться в подкаталоге `new`), либо «cur» (если сообщение должно храниться в подкаталоге `cur`).

> **Примечание**
>
> Сообщение обычно перемещается из `new` в `cur` после обращения к его почтовому ящику, независимо от того, было ли сообщение прочитано. Сообщение `msg` считается прочитанным, если `"S" in msg.get_flags()` равно `True`.

#### `set_subdir(subdir)`

Устанавливает подкаталог, в котором должно храниться сообщение. Параметр

*subdir*

должен быть либо «new», либо «cur».

#### `get_flags()`

Возвращает строку с указанием установленных в данный момент флагов. Если сообщение соответствует стандартному формату Maildir, результатом будет конкатенация в алфавитном порядке не более одного вхождения каждого из

`'D'`

,

`'F'`

,

`'P'`

,

`'R'`

,

`'S'`

и

`'T'`

. Пустая строка возвращается, если флаги не установлены или если «info» содержит экспериментальную семантику.

#### `set_flags(flags)`

Устанавливает флаги, указанные

*flags*

, и сбрасывает все остальные.

#### `add_flag(flag)`

Устанавливает флаг(и), указанные

*flag*

, не изменяя остальные флаги. Чтобы добавить более одного флага за раз,

*flag*

может быть строкой из более чем одного символа. Текущий «info» перезаписывается, независимо от того, содержит ли он экспериментальную информацию вместо флагов.

#### `remove_flag(flag)`

Сбрасывает флаг(и), указанные в

*flag*

, не изменяя другие флаги. Чтобы удалить несколько флагов за раз,

*flag*

может быть строкой из более чем одного символа. Если «info» содержит экспериментальную информацию, а не флаги, текущий «info» не изменяется.

#### `get_date()`

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

#### `set_date(date)`

Устанавливает дату доставки сообщения в

*date*

, число с плавающей запятой, представляющее количество секунд с начала эпохи.

#### `get_info()`

Возвращает строку, содержащую «info» для сообщения. Это полезно для доступа к экспериментальному «info» и его изменения (т.е. не являющегося списком флагов).

#### `set_info(info)`

Устанавливает «info» в

*info*

, которое должно быть строкой.

Когда экземпляр [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) создается на основе экземпляра [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage), заголовки *Status* и *X-Status* опускаются, и выполняются следующие преобразования:

| Результирующее состояние | [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) состояние |
| --- | --- |
| Подкаталог «cur» | Флаг O |
| Флаг F | Флаг F |
| Флаг R | Флаг A |
| Флаг S | Флаг R |
| Флаг T | Флаг D |

Когда экземпляр [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) создается на основе экземпляра [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) состояние |
| --- | --- |
| Подкаталог «cur» | последовательность «unseen» |
| подкаталог «cur» и флаг S | нет последовательности «unseen» |
| Флаг F | последовательность «flagged» |
| Флаг R | последовательность «replied» |

Когда экземпляр [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) создается на основе экземпляра [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage), выполняются следующие преобразования:

| Результирующее состояние | [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) состояние |
| --- | --- |
| Подкаталог «cur» | метка «unseen» |
| подкаталог «cur» и флаг S | нет метки «unseen» |
| Флаг P | метка «forwarded» или «resent» |
| Флаг R | метка «отвечено» |
| Флаг T | метка «удалено» |

### 18.4.2.2. [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage)

#### `class mailbox.mboxMessage(message=None)`

Сообщение с поведением, специфичным для mbox. Параметр *message* имеет то же значение, что и в конструкторе [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message).

Сообщения в почтовом ящике mbox хранятся вместе в одном файле. Адрес отправителя (envelope address) и время доставки обычно хранятся в строке, начинающейся с «From », которая используется для обозначения начала сообщения, хотя точный формат этих данных сильно различается в разных реализациях mbox. Флаги, указывающие на состояние сообщения, такие как прочитано или помечено как важное, обычно хранятся в заголовках *Status* и *X-Status*.

Обычные флаги для сообщений mbox:

| Флаг | Значение | Пояснение |
| --- | --- | --- |
| R | Прочитано | Прочитано |
| O | Старое | Ранее обнаружено почтовым клиентом |
| D | Удалено | Помечено для последующего удаления |
| F | Помечено | Помечено как важное |
| A | Отвечено | Получен ответ |

Флаги «R» и «O» хранятся в заголовке *Status*, а флаги «D», «F» и «A» – в заголовке *X-Status*. Флаги и заголовки обычно располагаются в указанном порядке.

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

#### `get_from()`

Возвращает строку, представляющую строку «From », отмечающую начало сообщения в почтовом ящике mbox. Начальная «From » и конечный символ новой строки исключаются.

#### `set_from(from_, time_=None)`

Устанавливает строку «From » в

*from\_*

, которая должна быть указана без ведущего «From » или завершающего символа новой строки. Для удобства можно указать

*time\_*

; он будет отформатирован соответствующим образом и добавлен к

*from\_*

. Если

*time\_*

указан, он должен быть экземпляром

`struct_time`

, кортежем, подходящим для передачи в

[`time.strftime()`](https://python-all.ru/3.1/library/time.html#time.strftime)

, или

`True`

(для использования

[`time.gmtime()`](https://python-all.ru/3.1/library/time.html#time.gmtime)

).

#### `get_flags()`

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

`'R'`

,

`'O'`

,

`'D'`

,

`'F'`

и

`'A'`

.

#### `set_flags(flags)`

Устанавливает флаги, указанные параметром

*flags*

, и сбрасывает все остальные. Параметр

*flags*

должен быть конкатенацией в любом порядке нуля или более вхождений каждого из

`'R'`

,

`'O'`

,

`'D'`

,

`'F'`

и

`'A'`

.

#### `add_flag(flag)`

Устанавливает флаг(и), указанные в

*flag*

, не изменяя другие флаги. Чтобы добавить более одного флага за раз,

*flag*

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

#### `remove_flag(flag)`

Снимает флаг(и), указанные в

*flag*

, не изменяя другие флаги. Чтобы снять несколько флагов одновременно,

*flag*

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

Когда экземпляр [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) создается на основе экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), строка «From » генерируется на основе даты доставки экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), и выполняются следующие преобразования:

| Результирующее состояние | [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) состояние |
| --- | --- |
| Флаг R | Флаг S |
| Флаг O | Подкаталог «cur» |
| Флаг D | Флаг T |
| Флаг F | Флаг F |
| Флаг A | Флаг R |

Когда экземпляр [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) создаётся на основе экземпляра [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) состояние |
| --- | --- |
| Флаг R и флаг O | нет последовательности «unseen» |
| Флаг O | последовательность «unseen» |
| Флаг F | последовательность «flagged» |
| Флаг A | последовательность «replied» |

Когда экземпляр [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) создаётся на основе экземпляра [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage), выполняются следующие преобразования:

| Результирующее состояние | [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) состояние |
| --- | --- |
| Флаг R и флаг O | нет метки «unseen» |
| Флаг O | метка «unseen» |
| Флаг D | метка «удалено» |
| Флаг A | метка «отвечено» |

Когда экземпляр [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message) создаётся на основе экземпляра [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) , строка «From » копируется, и все флаги напрямую соответствуют:

| Результирующее состояние | состояние [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) |
| --- | --- |
| Флаг R | Флаг R |
| Флаг O | Флаг O |
| Флаг D | Флаг D |
| Флаг F | Флаг F |
| Флаг A | Флаг A |

### 18.4.2.3. [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage)

#### `class mailbox.MHMessage(message=None)`

Сообщение с поведением, специфичным для MH. Параметр *message* имеет тот же смысл, что и в конструкторе [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message).

Сообщения MH не поддерживают метки и флаги в традиционном понимании, но поддерживают последовательности – логические группировки произвольных сообщений. Некоторые почтовые программы (хотя не стандартные **mh** и **nmh**) используют последовательности примерно так же, как флаги используются в других форматах:

| Последовательность | Пояснение |
| --- | --- |
| непрочитанное | Не прочитано, но ранее обнаружено почтовым клиентом (MUA) |
| отвечено | Получен ответ |
| помечено | Помечено как важное |

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

#### `get_sequences()`

Возвращает список имен последовательностей, которые включают это сообщение.

#### `set_sequences(sequences)`

Устанавливает список последовательностей, которые включают это сообщение.

#### `add_sequence(sequence)`

Добавляет

*sequence*

в список последовательностей, которые включают это сообщение.

#### `remove_sequence(sequence)`

Удаляет

*sequence*

из списка последовательностей, которые включают это сообщение.

Когда экземпляр [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) создаётся на основе экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) состояние |
| --- | --- |
| последовательность «unseen» | нет флага S |
| последовательность «replied» | Флаг R |
| последовательность «flagged» | Флаг F |

Когда экземпляр [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) создаётся на основе экземпляра [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage), заголовки *Status* и *X-Status* опускаются, и выполняются следующие преобразования:

| Результирующее состояние | [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) состояние |
| --- | --- |
| последовательность «unseen» | нет флага R |
| последовательность «replied» | Флаг A |
| последовательность «flagged» | Флаг F |

Когда экземпляр [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) создаётся на основе экземпляра [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage), выполняются следующие преобразования:

| Результирующее состояние | [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) состояние |
| --- | --- |
| последовательность «unseen» | метка «unseen» |
| последовательность «replied» | метка «отвечено» |

### 18.4.2.4. [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage)

#### `class mailbox.BabylMessage(message=None)`

Сообщение с поведением, специфичным для Babyl. Параметр *message* имеет тот же смысл, что и в конструкторе [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message).

Некоторые метки сообщений, называемые *attributes*, по соглашению имеют специальное значение. Атрибуты следующие:

| Метка | Пояснение |
| --- | --- |
| непрочитанное | Не прочитано, но ранее обнаружено почтовым клиентом (MUA) |
| удалено | Помечено для последующего удаления |
| архивировано | Скопировано в другой файл или почтовый ящик |
| отвечено | Получен ответ |
| переслано | Переслано |
| изменено | Изменено пользователем |
| переотправлено | Отправлено повторно |

По умолчанию Rmail отображает только видимые заголовки. Класс [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) , однако, использует оригинальные заголовки, поскольку они более полны. К видимым заголовкам можно обратиться явно при желании.

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

#### `get_labels()`

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

#### `set_labels(labels)`

Устанавливает список меток сообщения равным

*labels*

.

#### `add_label(label)`

Добавляет метку

*label*

в список меток сообщения.

#### `remove_label(label)`

Удаляет метку

*label*

из списка меток сообщения.

#### `get_visible()`

Возвращает экземпляр

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

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

#### `set_visible(visible)`

Устанавливает видимые заголовки сообщения такими же, как заголовки в

*message*

. Параметр

*visible*

должен быть экземпляром

[`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message)

, экземпляром

`email.Message.Message`

, строкой или файлоподобным объектом (который должен быть открыт в текстовом режиме).

#### `update_visible()`

Когда изменяются исходные заголовки экземпляра

[`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage)

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

*Date*

,

*From*

,

*Reply-To*

,

*To*

,

*CC*

и

*Subject*

, которые присутствуют в исходных заголовках, но отсутствуют среди видимых, добавляются к видимым заголовкам.

Когда экземпляр [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) создаётся на основе экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) состояние |
| --- | --- |
| метка «unseen» | нет флага S |
| метка «удалено» | Флаг T |
| метка «отвечено» | Флаг R |
| Метка «forwarded» | Флаг P |

Когда экземпляр [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) создаётся на основе экземпляра [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage), заголовки *Status* и *X-Status* опускаются и выполняются следующие преобразования:

| Результирующее состояние | [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) или [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) состояние |
| --- | --- |
| метка «unseen» | нет флага R |
| метка «удалено» | Флаг D |
| метка «отвечено» | Флаг A |

Когда экземпляр [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) создаётся на основе экземпляра [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) состояние |
| --- | --- |
| метка «unseen» | последовательность «unseen» |
| метка «отвечено» | последовательность «replied» |

### 18.4.2.5. [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage)

#### `class mailbox.MMDFMessage(message=None)`

Сообщение с поведением, специфичным для MMDF. Параметр *message* имеет то же значение, что и в конструкторе [`Message`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Message).

Как и сообщения в почтовом ящике mbox, сообщения MMDF хранятся с адресом отправителя и датой доставки в начальной строке, начинающейся с «From ». Аналогично, флаги, указывающие на состояние сообщения, обычно хранятся в заголовках *Status* и *X-Status*.

Стандартные флаги для сообщений MMDF совпадают с флагами сообщений mbox и перечислены ниже:

| Флаг | Значение | Пояснение |
| --- | --- | --- |
| R | Прочитано | Прочитано |
| O | Старое | Ранее обнаружено почтовым клиентом |
| D | Удалено | Помечено для последующего удаления |
| F | Помечено | Помечено как важное |
| A | Отвечено | Получен ответ |

Флаги «R» и «O» хранятся в заголовке *Status*, а флаги «D», «F» и «A» – в заголовке *X-Status*. Флаги и заголовки обычно располагаются в указанном порядке.

Экземпляры [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) предоставляют следующие методы, идентичные методам, предоставляемым [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage):

#### `get_from()`

Возвращает строку, представляющую строку «From », отмечающую начало сообщения в почтовом ящике mbox. Начальная «From » и конечный символ новой строки исключаются.

#### `set_from(from_, time_=None)`

Устанавливает строку «From » в

*from\_*

, которая должна быть указана без ведущего «From » или завершающего символа новой строки. Для удобства можно указать

*time\_*

; он будет отформатирован соответствующим образом и добавлен к

*from\_*

. Если

*time\_*

указан, он должен быть экземпляром

`struct_time`

, кортежем, подходящим для передачи в

[`time.strftime()`](https://python-all.ru/3.1/library/time.html#time.strftime)

, или

`True`

(для использования

[`time.gmtime()`](https://python-all.ru/3.1/library/time.html#time.gmtime)

).

#### `get_flags()`

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

`'R'`

,

`'O'`

,

`'D'`

,

`'F'`

и

`'A'`

.

#### `set_flags(flags)`

Устанавливает флаги, указанные параметром

*flags*

, и сбрасывает все остальные. Параметр

*flags*

должен быть конкатенацией в любом порядке нуля или более вхождений каждого из

`'R'`

,

`'O'`

,

`'D'`

,

`'F'`

и

`'A'`

.

#### `add_flag(flag)`

Устанавливает флаг(и), указанные в

*flag*

, не изменяя другие флаги. Чтобы добавить более одного флага за раз,

*flag*

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

#### `remove_flag(flag)`

Снимает флаг(и), указанные в

*flag*

, не изменяя другие флаги. Чтобы снять несколько флагов одновременно,

*flag*

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

Когда экземпляр [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) создаётся на основе экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), строка «From » генерируется на основе даты доставки экземпляра [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage), и выполняются следующие преобразования:

| Результирующее состояние | [`MaildirMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MaildirMessage) состояние |
| --- | --- |
| Флаг R | Флаг S |
| Флаг O | Подкаталог «cur» |
| Флаг D | Флаг T |
| Флаг F | Флаг F |
| Флаг A | Флаг R |

Когда экземпляр [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) создаётся на основе экземпляра [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage), выполняются следующие преобразования:

| Результирующее состояние | [`MHMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MHMessage) состояние |
| --- | --- |
| Флаг R и флаг O | нет последовательности «unseen» |
| Флаг O | последовательность «unseen» |
| Флаг F | последовательность «flagged» |
| Флаг A | последовательность «replied» |

Когда экземпляр [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) создаётся на основе экземпляра [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage), выполняются следующие преобразования:

| Результирующее состояние | [`BabylMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.BabylMessage) состояние |
| --- | --- |
| Флаг R и флаг O | нет метки «unseen» |
| Флаг O | метка «unseen» |
| Флаг D | метка «удалено» |
| Флаг A | метка «отвечено» |

Когда экземпляр [`MMDFMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MMDFMessage) создаётся на основе экземпляра [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage), строка «From » копируется и все флаги напрямую соответствуют:

| Результирующее состояние | [`mboxMessage`](https://python-all.ru/3.1/library/mailbox.html#mailbox.mboxMessage) состояние |
| --- | --- |
| Флаг R | Флаг R |
| Флаг O | Флаг O |
| Флаг D | Флаг D |
| Флаг F | Флаг F |
| Флаг A | Флаг A |

## 18.4.3. Исключения

В модуле `mailbox` определены следующие классы исключений:

#### `exception mailbox.Error`

Базовый класс для всех остальных исключений, специфичных для модуля.

#### `exception mailbox.NoSuchMailboxError`

Возникает, когда ожидается почтовый ящик, но он не найден, например, при создании экземпляра подкласса

[`Mailbox`](https://python-all.ru/3.1/library/mailbox.html#mailbox.Mailbox)

с несуществующим путём (и с параметром

*create*

, установленным в

`False`

), или при открытии несуществующей папки.

#### `exception mailbox.NotEmptyError`

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

#### `exception mailbox.ExternalClashError`

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

#### `exception mailbox.FormatError`

Возникает, когда данные в файле не могут быть разобраны, например, когда экземпляр

[`MH`](https://python-all.ru/3.1/library/mailbox.html#mailbox.MH)

пытается прочитать повреждённый файл

`.mh_sequences`

.

## 18.4.4. Примеры

Простой пример вывода тем всех сообщений в почтовом ящике, которые кажутся интересными:

```python
import mailbox
for message in mailbox.mbox('~/mbox'):
    subject = message['subject']       # Может быть None.
    if subject and 'python' in subject.lower():
        print(subject)
```

Чтобы скопировать все письма из почтового ящика Babyl в почтовый ящик MH, преобразуя всю форматно-специфичную информацию, которую можно преобразовать:

```python
import mailbox
destination = mailbox.MH('~/Mail')
destination.lock()
for message in mailbox.Babyl('~/RMAIL'):
    destination.add(mailbox.MHMessage(message))
destination.flush()
destination.unlock()
```

Этот пример сортирует письма из нескольких списков рассылки по разным почтовым ящикам, стараясь избежать повреждения писем из-за одновременного изменения другими программами, потери писем из-за прерывания программы или преждевременного завершения из-за повреждённых сообщений в почтовом ящике:

```python
import mailbox
import email.Errors

list_names = ('python-list', 'python-dev', 'python-bugs')

boxes = {name: mailbox.mbox('~/email/%s' % name) for name in list_names}
inbox = mailbox.Maildir('~/Maildir', factory=None)

for key in inbox.iterkeys():
    try:
        message = inbox[key]
    except email.Errors.MessageParseError:
        continue                # Сообщение повреждено. Просто оставьте его.

    for name in list_names:
        list_id = message['list-id']
        if list_id and name in list_id:
            # Получить почтовый ящик для использования.
            box = boxes[name]

            # Записать копию на диск перед удалением оригинала.
            # Если произошёл сбой, возможно дублирование сообщения, но
            # это лучше, чем полная потеря сообщения.
            box.lock()
            box.add(message)
            box.flush()
            box.unlock()

            # Удалить исходное сообщение
            inbox.lock()
            inbox.discard(key)
            inbox.flush()
            inbox.unlock()
            break               # Целевой получатель найден, поиск прекращён.

for box in boxes.itervalues():
    box.close()
```
