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

19.4. mailbox – Управление почтовыми ящиками в различных форматахmailbox – Manipulate mailboxes in various formats

Исходный код: Lib/mailbox.py


Этот модуль определяет два класса: Mailbox и Message для доступа к почтовым ящикам на диске и управления ими, а также для работы с содержащимися в них сообщениями. Mailbox предоставляет словареподобное отображение ключей на сообщения. Message расширяет класс Message из модуля email.message, добавляя формат-специфичное состояние и поведение. Поддерживаемые форматы почтовых ящиков: Maildir, mbox, MH, Babyl и MMDF.

См. также

Модуль email

Представление сообщений и управление ими.

19.4.1. Mailbox объектыMailbox objects

class mailbox.Mailbox

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

Класс Mailbox определяет интерфейс и не предназначен для создания экземпляров. Вместо этого следует наследовать формат-специфичные подклассы от Mailbox, а код должен создавать экземпляры конкретного подкласса.

Интерфейс Mailbox напоминает словарь: небольшие ключи соответствуют сообщениям. Ключи выдаются экземпляром Mailbox, с которым они будут использоваться, и имеют смысл только для этого экземпляра Mailbox. Ключ продолжает идентифицировать сообщение, даже если соответствующее сообщение изменяется, например, заменяется другим сообщением.

Сообщения можно добавлять в экземпляр Mailbox с помощью метода add() (подобного set) и удалять с помощью инструкции del или методов remove() и discard() (также подобных set).

Семантика интерфейса Mailbox отличается от семантики словаря в некоторых важных аспектах. При каждом запросе сообщения на основе текущего состояния почтового ящика создаётся новое представление (обычно экземпляр Message). Аналогично, при добавлении сообщения в экземпляр Mailbox содержимое переданного представления сообщения копируется. Ни в одном из случаев экземпляр Mailbox не сохраняет ссылку на представление сообщения.

Итератор по умолчанию Mailbox перебирает представления сообщений, а не ключи, как это делает итератор словаря по умолчанию. Кроме того, изменение почтового ящика во время итерации безопасно и хорошо определено. Сообщения, добавленные в почтовый ящик после создания итератора, не будут видны итератору. Сообщения, удалённые из почтового ящика до того, как итератор их вернёт, будут молча пропущены, хотя использование ключа из итератора может привести к исключению KeyError, если соответствующее сообщение будет впоследствии удалено.

Предупреждение

Будьте предельно осторожны при изменении почтовых ящиков, которые могут одновременно изменяться другим процессом. Самый безопасный формат почтового ящика для таких задач – Maildir; старайтесь избегать использования однофайловых форматов, таких как mbox, для одновременной записи. Если вы изменяете почтовый ящик, вы должны заблокировать его, вызвав методы lock() и unlock() перед чтением любых сообщений в файле или внесением каких-либо изменений путём добавления или удаления сообщения. Несоблюдение блокировки почтового ящика чревато потерей сообщений или повреждением всего почтового ящика.

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

add(message)

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

Параметр message может быть экземпляром Message, экземпляром email.message.Message, строкой, байтовой строкой или файлоподобным объектом (который должен быть открыт в двоичном режиме). Если message является экземпляром соответствующего формат-специфичного подкласса Message (например, если это экземпляр mboxMessage, а это экземпляр mbox), используется его формат-специфичная информация. В противном случае используются разумные значения по умолчанию для формат-специфичной информации.

Изменено в версии 3.2: Добавлена поддержка двоичного ввода.

remove(key)
__delitem__(key)
discard(key)

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

Если такого сообщения не существует, возникает исключение KeyError, если метод был вызван как remove() или __delitem__(), но исключение не возникает, если метод был вызван как discard(). Поведение discard() может быть предпочтительнее, если базовый формат почтового ящика поддерживает одновременное изменение другими процессами.

__setitem__(key, message)

Заменяет сообщение, соответствующее ключу, на сообщение. Возникает исключение KeyError, если ключу ещё не соответствует ни одно сообщение.

Как и в случае с add(), параметр message может быть экземпляром Message, экземпляром email.message.Message, строкой, байтовой строкой или файлоподобным объектом (который должен быть открыт в двоичном режиме). Если message является экземпляром соответствующего формат-специфичного подкласса Message (например, если это экземпляр mboxMessage, а это экземпляр mbox), используется его формат-специфичная информация. В противном случае формат-специфичная информация сообщения, которое в данный момент соответствует ключу, остаётся неизменной.

iterkeys()
keys()

Возвращает итератор по всем ключам, если вызван как iterkeys(), или возвращает список ключей, если вызван как keys().

itervalues()
__iter__()
values()

Возвращает итератор по представлениям всех сообщений, если вызван как itervalues() или __iter__(), или возвращает список таких представлений, если вызван как values(). Сообщения представлены в виде экземпляров соответствующего подкласса Message, зависящего от формата, если только при инициализации экземпляра Mailbox не была указана пользовательская фабрика сообщений.

Примечание

Поведение __iter__() отличается от поведения словарей, которые перебирают ключи.

iteritems()
items()

Возвращает итератор по парам (key, message), где key – ключ, а message – представление сообщения, если вызван как iteritems(), или возвращает список таких пар, если вызван как items(). Сообщения представлены в виде экземпляров соответствующего подкласса Message, зависящего от формата, если только при инициализации экземпляра Mailbox не была указана пользовательская фабрика сообщений.

get(key, default=None)
__getitem__(key)

Возвращает представление сообщения, соответствующего ключу. Если такого сообщения нет, default возвращается, если метод был вызван как get(), и вызывается исключение KeyError, если метод был вызван как __getitem__(). Сообщение представляется в виде экземпляра соответствующего подкласса Message, если только при инициализации экземпляра Mailbox не была указана пользовательская фабрика сообщений.

get_message(key)

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

get_bytes(key)

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

Новое в версии 3.2.

get_string(key)

Возвращает строковое представление сообщения, соответствующего ключу, или вызывает исключение KeyError, если такого сообщения нет. Сообщение обрабатывается через email.message.Message для преобразования в 7-битное чистое представление.

get_file(key)

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

Изменено в версии 3.2: Файловый объект на самом деле является двоичным файлом; ранее он некорректно возвращался в текстовом режиме. Кроме того, файлоподобный объект теперь поддерживает протокол управления контекстом: для автоматического закрытия можно использовать оператор with.

Примечание

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

__contains__(key)

Возвращает True, если ключ соответствует сообщению, и False в противном случае.

__len__()

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

clear()

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

pop(key, default=None)

Возвращает представление сообщения, соответствующего ключу, и удаляет сообщение. Если такого сообщения нет, возвращает default. Сообщение представляется в виде экземпляра соответствующего подкласса Message, если только при инициализации экземпляра Mailbox не была указана пользовательская фабрика сообщений.

popitem()

Возвращает произвольную пару (ключ, сообщение), где ключ – это ключ, а сообщение – представление сообщения, и удаляет соответствующее сообщение. Если почтовый ящик пуст, вызывает исключение KeyError. Сообщение представляется в виде экземпляра соответствующего подкласса Message, если только при инициализации экземпляра Mailbox не была указана пользовательская фабрика сообщений.

update(arg)

Параметр arg должен быть отображением ключсообщение или итерируемым объектом из пар (ключ, сообщение). Обновляет почтовый ящик так, что для каждой заданной пары ключ и сообщение сообщение, соответствующее ключу, устанавливается в сообщение как если бы с помощью __setitem__(). Как и в случае с __setitem__(), каждый ключ уже должен соответствовать сообщению в почтовом ящике, иначе будет вызвано исключение KeyError, поэтому в общем случае неправильно, чтобы arg был экземпляром Mailbox.

Примечание

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

flush()

Записывает все ожидающие изменения в файловую систему. Для некоторых подклассов Mailbox изменения всегда записываются сразу, и flush() ничего не делает, но всё же стоит выработать привычку вызывать этот метод.

lock()

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

unlock()

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

close()

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

19.4.1.1. Maildir

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

Подкласс Mailbox для почтовых ящиков в формате Maildir. Параметр factory – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя как открытое в бинарном режиме) и возвращает пользовательское представление. Если factory равно None, в качестве представления сообщения по умолчанию используется MaildirMessage. Если create равно True, почтовый ящик создаётся, если он не существует.

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

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

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

Также поддерживаются папки в стиле, введённом агентом передачи почты Courier. Любой подкаталог основного почтового ящика считается папкой, если первым символом в его имени является '.'. Имена папок представляются как Maildir без ведущего '.'. Каждая папка сама является почтовым ящиком Maildir, но не должна содержать другие папки. Вместо этого логическая вложенность указывается с помощью '.' для разделения уровней, например, «Archived.2005.07».

Примечание

Спецификация Maildir требует использования двоеточия (':') в некоторых именах файлов сообщений. Однако некоторые операционные системы не допускают этот символ в именах файлов. Если вы хотите использовать формат, подобный Maildir, в такой операционной системе, следует указать другой символ для замены. Восклицательный знак ('!') – популярный выбор. Например:

import mailbox
mailbox.Maildir.colon = '!'

Атрибут colon также может быть установлен для каждого экземпляра отдельно.

Экземпляры Maildir имеют все методы Mailbox, а также следующие:

list_folders()

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

get_folder(folder)

Возвращает экземпляр Maildir, представляющий папку с именем folder. Если папка не существует, возбуждается исключение NoSuchMailboxError.

add_folder(folder)

Создаёт папку с именем folder и возвращает экземпляр Maildir, представляющий её.

remove_folder(folder)

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

clean()

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

Некоторые методы Mailbox, реализованные в Maildir, заслуживают особых замечаний:

add(message)
__setitem__(key, message)
update(arg)

Предупреждение

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

flush()

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

lock()
unlock()

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

close()

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

get_file(key)

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

См. также

Страница руководства maildir из qmail

Оригинальная спецификация формата.

Использование формата maildir

Заметки о Maildir от его создателя. Включают обновлённую схему создания имён и детали семантики «info».

man-страница maildir из Courier

Другая спецификация формата. Описывает распространённое расширение для поддержки папок.

19.4.1.2. mbox

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

Подкласс Mailbox для почтовых ящиков в формате mbox. Параметр factory – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя как открытое в бинарном режиме) и возвращает пользовательское представление. Если factory равен None, в качестве представления сообщения по умолчанию используется mboxMessage. Если create равен True, почтовый ящик создаётся, если он не существует.

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

Существует несколько вариантов формата mbox, призванных устранить недостатки исходного. В целях совместимости mbox реализует исходный формат, иногда называемый mboxo. Это означает, что заголовок Content-Length, если он присутствует, игнорируется, а все вхождения «From » в начале строки тела сообщения преобразуются в «>From » при сохранении сообщения, хотя вхождения «>From » не преобразуются обратно в «From » при чтении сообщения.

Некоторые методы Mailbox, реализованные в mbox, заслуживают особых замечаний:

get_file(key)

Использование файла после вызова flush() или close() для экземпляра mbox может привести к непредсказуемым результатам или вызвать исключение.

lock()
unlock()

Используются три механизма блокировки: точечная блокировка (dot locking) и, если доступны, системные вызовы flock() и lockf().

См. также

Страница руководства mbox из qmail

Спецификация формата и его разновидностей.

Страница man mbox из tin

Другая спецификация формата, с подробностями о блокировке.

Настройка Netscape Mail в Unix: почему формат Content-Length плох

Аргумент в пользу использования оригинального формата mbox, а не его вариации.

«mbox» – это семейство нескольких взаимно несовместимых форматов почтовых ящиков

История вариаций mbox.

19.4.1.3. MH

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

Подкласс Mailbox для почтовых ящиков в формате MH. Параметр factory – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя как открытое в бинарном режиме) и возвращает пользовательское представление. Если factory равен None, в качестве представления сообщения по умолчанию используется MHMessage. Если create равен True, почтовый ящик создаётся, если он не существует.

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

Класс MH управляет почтовыми ящиками MH, но не пытается эмулировать все поведения mh. В частности, он не изменяет и не зависит от файлов context и .mh_profile, которые используются программой mh для хранения своего состояния и конфигурации.

Экземпляры MH имеют все методы Mailbox, а также следующие:

list_folders()

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

get_folder(folder)

Возвращает экземпляр MH, представляющий папку с именем folder. Исключение NoSuchMailboxError возникает, если папка не существует.

add_folder(folder)

Создаёт папку с именем folder и возвращает экземпляр MH представляющий её.

remove_folder(folder)

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

get_sequences()

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

set_sequences(sequences)

Переопределяет последовательности, существующие в почтовом ящике, на основе sequences, словаря, где имена сопоставлены со списками ключей, аналогично возвращаемому get_sequences().

pack()

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

Примечание

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

Некоторые методы Mailbox, реализованные в MH, заслуживают особых замечаний:

remove(key)
__delitem__(key)
discard(key)

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

lock()
unlock()

Используются три механизма блокировки: точечная блокировка и, если доступны, системные вызовы flock() и lockf(). Для почтовых ящиков MH блокировка почтового ящика означает блокировку файла .mh_sequences и, только на время любых операций, затрагивающих их, блокировку отдельных файлов сообщений.

get_file(key)

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

flush()

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

close()

Экземпляры MH не держат открытых файлов, поэтому этот метод эквивалентен unlock().

См. также

nmh – система обработки сообщений

Домашняя страница nmh, обновлённой версии исходного mh.

MH и nmh: электронная почта для пользователей и программистов

Книга, лицензированная под GPL, о mh и nmh, с некоторой информацией о формате почтового ящика.

19.4.1.4. Babyl

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

Подкласс Mailbox для почтовых ящиков в формате Babyl. Параметр factory – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя как открытое в бинарном режиме) и возвращает пользовательское представление. Если factory равно None, в качестве представления сообщения по умолчанию используется BabylMessage. Если create равно True, почтовый ящик создаётся, если он не существует.

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

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

Экземпляры Babyl имеют все методы Mailbox, а также следующие:

get_labels()

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

Примечание

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

Некоторые методы Mailbox, реализованные в Babyl, заслуживают особых замечаний:

get_file(key)

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

lock()
unlock()

Используются три механизма блокировки: точечная блокировка (dot locking) и, если доступны, системные вызовы flock() и lockf().

См. также

Формат файлов Babyl версии 5

Спецификация формата Babyl.

Чтение почты с помощью Rmail

Руководство по Rmail, содержащее некоторую информацию о семантике Babyl.

19.4.1.5. MMDF

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

Подкласс Mailbox для почтовых ящиков в формате MMDF. Параметр factory – это вызываемый объект, который принимает файлоподобное представление сообщения (ведущее себя так, как если бы оно было открыто в двоичном режиме) и возвращает пользовательское представление. Если factory равно None, в качестве представления сообщения по умолчанию используется MMDFMessage. Если create равно True, почтовый ящик создаётся, если он не существует.

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

Некоторые методы Mailbox, реализованные в MMDF, заслуживают особых замечаний:

get_file(key)

Использование файла после вызова flush() или close() для экземпляра MMDF может привести к непредсказуемым результатам или вызвать исключение.

lock()
unlock()

Используются три механизма блокировки: точечная блокировка (dot locking) и, если доступны, системные вызовы flock() и lockf().

См. также

страница руководства mmdf из tin

Спецификация формата MMDF из документации tin, программы для чтения новостей.

MMDF

Статья в Википедии, описывающая Multichannel Memorandum Distribution Facility.

19.4.2. Message объектыMessage objects

class mailbox.Message(message=None)

Подкласс email.message модуля Message. Подклассы mailbox.Message добавляют состояние и поведение, специфичные для формата почтового ящика.

Если message опущен, создаётся новый экземпляр в пустом состоянии по умолчанию. Если message – экземпляр email.message.Message, его содержимое копируется; кроме того, любая форматозависимая информация преобразуется настолько, насколько это возможно, если message является экземпляром Message. Если message – строка, байтовая строка или файл, он должен содержать сообщение, совместимое с RFC 2822, которое читается и разбирается. Файлы должны быть открыты в бинарном режиме, но текстовые файлы принимаются для обратной совместимости.

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

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

19.4.2.1. MaildirMessage

class mailbox.MaildirMessage(message=None)

Сообщение с поведением, специфичным для Maildir. Параметр message имеет то же значение, что и в конструкторе Message.

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

Флаг

Значение

Пояснение

D

Черновик

В процессе составления

F

Помечено

Помечено как важное

P

Передан

Переслано, отправлено повторно или возвращено

R

Отвечено

Получен ответ

S

Просмотрено

Прочитано

T

Удалено

Помечено для последующего удаления

Экземпляры 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 создаётся на основе экземпляра mboxMessage или MMDFMessage, заголовки Status и X-Status опускаются и происходят следующие преобразования:

Результирующее состояние

mboxMessage или MMDFMessage состояние

Подкаталог «cur»

Флаг O

Флаг F

Флаг F

Флаг R

Флаг A

Флаг S

Флаг R

Флаг T

Флаг D

Когда экземпляр MaildirMessage создаётся на основе экземпляра MHMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MHMessage

Подкаталог «cur»

последовательность «unseen»

подкаталог «cur» и флаг S

нет последовательности «unseen»

Флаг F

последовательность «flagged»

Флаг R

последовательность «replied»

Когда экземпляр MaildirMessage создаётся на основе экземпляра BabylMessage, происходят следующие преобразования:

Результирующее состояние

Состояние BabylMessage

Подкаталог «cur»

метка «unseen»

подкаталог «cur» и флаг S

нет метки «unseen»

Флаг P

метка «forwarded» или «resent»

Флаг R

метка «отвечено»

Флаг T

метка «удалено»

19.4.2.2. mboxMessage

class mailbox.mboxMessage(message=None)

Сообщение с поведением, специфичным для mbox. Параметр message имеет тот же смысл, что и в конструкторе Message.

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

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

Флаг

Значение

Пояснение

R

Прочитано

Прочитано

O

Старое

Ранее обнаружено почтовым клиентом

D

Удалено

Помечено для последующего удаления

F

Помечено

Помечено как важное

A

Отвечено

Получен ответ

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

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

get_from()

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

set_from(from_, time_=None)

Устанавливает строку «From » равной from_, которая должна быть указана без начальной «From » или конечного символа новой строки. Для удобства можно указать time_, и она будет правильно отформатирована и добавлена к from_. Если time_ указан, это должен быть экземпляр time.struct_time, кортеж, подходящий для передачи в time.strftime(), или True (для использования 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 создается на основе экземпляра MaildirMessage, строка «From » генерируется на основе даты доставки экземпляра MaildirMessage, и происходят следующие преобразования:

Результирующее состояние

Состояние MaildirMessage

Флаг R

Флаг S

Флаг O

Подкаталог «cur»

Флаг D

Флаг T

Флаг F

Флаг F

Флаг A

Флаг R

Когда экземпляр mboxMessage создаётся на основе экземпляра MHMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MHMessage

Флаг R и флаг O

нет последовательности «unseen»

Флаг O

последовательность «unseen»

Флаг F

последовательность «flagged»

Флаг A

последовательность «replied»

Когда экземпляр mboxMessage создаётся на основе экземпляра BabylMessage, происходят следующие преобразования:

Результирующее состояние

Состояние BabylMessage

Флаг R и флаг O

нет метки «unseen»

Флаг O

метка «unseen»

Флаг D

метка «удалено»

Флаг A

метка «отвечено»

Когда экземпляр Message создается на основе экземпляра MMDFMessage, строка «From » копируется, и все флаги напрямую соответствуют:

Результирующее состояние

Состояние MMDFMessage

Флаг R

Флаг R

Флаг O

Флаг O

Флаг D

Флаг D

Флаг F

Флаг F

Флаг A

Флаг A

19.4.2.3. MHMessage

class mailbox.MHMessage(message=None)

Сообщение с поведением, характерным для MH. Параметр message имеет то же значение, что и в конструкторе Message.

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

Последовательность

Пояснение

непрочитанное

Не прочитано, но ранее обнаружено почтовым клиентом (MUA)

отвечено

Получен ответ

помечено

Помечено как важное

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

get_sequences()

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

set_sequences(sequences)

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

add_sequence(sequence)

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

remove_sequence(sequence)

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

Когда экземпляр MHMessage создаётся на основе экземпляра MaildirMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MaildirMessage

последовательность «unseen»

нет флага S

последовательность «replied»

Флаг R

последовательность «flagged»

Флаг F

Когда экземпляр MHMessage создается на основе экземпляра mboxMessage или MMDFMessage, заголовки Status и X-Status опускаются и происходят следующие преобразования:

Результирующее состояние

mboxMessage или MMDFMessage состояние

последовательность «unseen»

нет флага R

последовательность «replied»

Флаг A

последовательность «flagged»

Флаг F

Когда экземпляр MHMessage создаётся на основе экземпляра BabylMessage, происходят следующие преобразования:

Результирующее состояние

Состояние BabylMessage

последовательность «unseen»

метка «unseen»

последовательность «replied»

метка «отвечено»

19.4.2.4. BabylMessage

class mailbox.BabylMessage(message=None)

Сообщение с поведением, специфичным для Babyl. Параметр message имеет то же значение, что и в конструкторе Message.

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

Метка

Пояснение

непрочитанное

Не прочитано, но ранее обнаружено почтовым клиентом (MUA)

удалено

Помечено для последующего удаления

архивировано

Скопировано в другой файл или почтовый ящик

отвечено

Получен ответ

переслано

Переслано

изменено

Изменено пользователем

переотправлено

Отправлено повторно

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

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

get_labels()

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

set_labels(labels)

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

add_label(label)

Добавляет метку label в список меток сообщения.

remove_label(label)

Удаляет метку label из списка меток сообщения.

get_visible()

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

set_visible(visible)

Устанавливает видимые заголовки сообщения такими же, как заголовки из message. Параметр visible должен быть экземпляром Message, экземпляром email.message.Message, строкой или файлоподобным объектом (который должен быть открыт в текстовом режиме).

update_visible()

Когда исходные заголовки экземпляра BabylMessage изменяются, видимые заголовки автоматически не изменяются для соответствия. Этот метод обновляет видимые заголовки следующим образом: каждый видимый заголовок с соответствующим исходным заголовком устанавливается в значение исходного заголовка, каждый видимый заголовок без соответствующего исходного заголовка удаляется, а любые из Date, From, Reply-To, To, CC и Subject, которые присутствуют в исходных заголовках, но отсутствуют в видимых заголовках, добавляются к видимым заголовкам.

Когда экземпляр BabylMessage создаётся на основе экземпляра MaildirMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MaildirMessage

метка «unseen»

нет флага S

метка «удалено»

Флаг T

метка «отвечено»

Флаг R

Метка «forwarded»

Флаг P

Когда экземпляр BabylMessage создаётся на основе экземпляра mboxMessage или MMDFMessage, заголовки Status и X-Status опускаются и происходят следующие преобразования:

Результирующее состояние

mboxMessage или MMDFMessage состояние

метка «unseen»

нет флага R

метка «удалено»

Флаг D

метка «отвечено»

Флаг A

Когда экземпляр BabylMessage создаётся на основе экземпляра MHMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MHMessage

метка «unseen»

последовательность «unseen»

метка «отвечено»

последовательность «replied»

19.4.2.5. MMDFMessage

class mailbox.MMDFMessage(message=None)

Сообщение с поведением, специфичным для MMDF. Параметр message имеет то же значение, что и в конструкторе Message.

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

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

Флаг

Значение

Пояснение

R

Прочитано

Прочитано

O

Старое

Ранее обнаружено почтовым клиентом

D

Удалено

Помечено для последующего удаления

F

Помечено

Помечено как важное

A

Отвечено

Получен ответ

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

Экземпляры MMDFMessage предоставляют следующие методы, идентичные методам, предоставляемым mboxMessage:

get_from()

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

set_from(from_, time_=None)

Устанавливает строку «From » равной from_, которая должна быть указана без начальной «From » или конечного символа новой строки. Для удобства можно указать time_, и она будет правильно отформатирована и добавлена к from_. Если time_ указан, это должен быть экземпляр time.struct_time, кортеж, подходящий для передачи в time.strftime(), или True (для использования 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 создается на основе экземпляра MaildirMessage, строка «From » генерируется на основе даты доставки экземпляра MaildirMessage, и происходят следующие преобразования:

Результирующее состояние

Состояние MaildirMessage

Флаг R

Флаг S

Флаг O

Подкаталог «cur»

Флаг D

Флаг T

Флаг F

Флаг F

Флаг A

Флаг R

Когда экземпляр MMDFMessage создаётся на основе экземпляра MHMessage, происходят следующие преобразования:

Результирующее состояние

Состояние MHMessage

Флаг R и флаг O

нет последовательности «unseen»

Флаг O

последовательность «unseen»

Флаг F

последовательность «flagged»

Флаг A

последовательность «replied»

Когда экземпляр MMDFMessage создаётся на основе экземпляра BabylMessage, происходят следующие преобразования:

Результирующее состояние

Состояние BabylMessage

Флаг R и флаг O

нет метки «unseen»

Флаг O

метка «unseen»

Флаг D

метка «удалено»

Флаг A

метка «отвечено»

Когда экземпляр MMDFMessage создается на основе экземпляра mboxMessage, строка «From » копируется, и все флаги напрямую соответствуют:

Результирующее состояние

Состояние mboxMessage

Флаг R

Флаг R

Флаг O

Флаг O

Флаг D

Флаг D

Флаг F

Флаг F

Флаг A

Флаг A

19.4.3. ИсключенияExceptions

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

exception mailbox.Error

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

exception mailbox.NoSuchMailboxError

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

exception mailbox.NotEmptyError

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

exception mailbox.ExternalClashError

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

exception mailbox.FormatError

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

19.4.4. ПримерыExamples

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

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

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

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

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

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()