Кратко

  • CLOSE переводил соединение из Selected в Authenticated и в доступном для записи ящике навсегда удалял все сообщения с флагом \Deleted. Отдельные ответы EXPUNGE при этом не отправлялись.
  • RFC 3691 определил UNSELECT: команда освобождает ресурсы выбранного ящика, но не удаляет сообщения. Один конечный статус получил два пути с разными полномочиями над данными.

Почтовая программа закончила работу с Inbox. Соединение и авторизация ещё нужны, а контекст выбранного ящика — нет. Намерение выглядит как простое освобождение ресурса.

Однако естественно названная команда CLOSE имела дополнительный смысл. В ящике, выбранном для записи, сервер навсегда удалял все сообщения с \Deleted, а затем возвращал соединение в Authenticated. Флаги могли появиться раньше или в другой сессии. Последний технический жест подтверждал весь накопленный набор.

В 2004 году RFC 3691 добавил недостающее слово. UNSELECT не имеет аргументов, освобождает связанное с выбором состояние и возвращает авторизованный режим, но не удаляет ни одного сообщения.

Небольшое расширение разделило две власти: покинуть рабочий контекст и необратимо изменить хранилище.

Selected был состоянием протокола

После авторизации клиент IMAP выбирает ящик, прежде чем искать, получать, помечать, копировать или удалять письма. В Selected сервер поддерживает конкретное представление ящика и сообщает относящиеся к нему изменения.

Отказ от представления не требует закрытия TCP или выхода из учётной записи. Клиент может выбрать другой ящик или остаться авторизованным для следующей операции. Переход в Authenticated полезен сам по себе.

CLOSE выполнял переход вместе с expunge. Диаграмма состояний показывает одинаковый конечный узел и скрывает путь: один вариант сохраняет письма, другой способен уничтожить их.

Флаг \Deleted ещё не является физическим удалением. Он готовит сообщение к последующему expunge. Разделение позволяет сначала отметить набор, затем пересмотреть его и только потом подтвердить. Но поставить флаг и запустить окончательное действие могут разные участники. Универсальный «выход» не должен незаметно присваивать себе решения всех предшественников.

Короткий ответ не означал безопасный результат

Обычный EXPUNGE отправляет ненумерованный ответ для каждого удалённого письма. В нём используется message sequence number — текущая позиция, которая сдвигается после исчезновения предыдущих сообщений.

CLOSE не отправляет этот ряд. Клиент покидает ящик и, вероятно, не станет использовать новые позиции. При большом числе удалений экономия ответов даёт выигрыш.

Но это экономия передачи, а не отсутствие мутации. Tagged OK подтверждает завершение CLOSE, не нулевое число удалений. Он также не даёт перечня устойчивых UID. Самое постоянное действие оказывается самым тихим.

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

Раньше безопасный выход выражался обходным путём

IMAP4rev1 разрешал сразу выбрать или исследовать другой ящик либо отправить LOGOUT. Текущий выбор завершался без expunge. Значит, сам результат был возможен.

Не было прямого выражения для сочетания: не выбирать ящик, остаться авторизованным, ничего не удалить. RFC 3691 описал два приёма. Клиент мог специально выбрать несуществующий ящик и использовать неудачу как переход в Authenticated. Либо повторно открыть тот же ящик через EXAMINE.

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

UNSELECT сделал намерение явным: снять выбор, сохранить авторизацию, не выполнять expunge.

Capability закрепляла общий словарь

Сервер IMAP4rev1 объявлял capability UNSELECT, если понимал расширение. Клиент проверял поддержку до отправки. Ошибка неизвестной команды не могла считаться успешным выходом: соединение могло остаться Selected.

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

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

IMAP4rev2 сделал различие базовым

RFC 9051 включил UNSELECT в основной набор IMAP4rev2. И CLOSE, и UNSELECT ведут из Selected в Authenticated, но их действие над данными не совпадает. Первый удаляет отмеченные сообщения в доступном для записи ящике, второй не удаляет ничего.

Переход расширения в базовый протокол показывает совместимое исправление. Старые обходы не переписаны, но обычное намерение больше не маскируется искусственной ошибкой или ненужным повторным выбором.

Та же проблема возникает повсюду. Соединение с базой закрывается после commit и после rollback; файл освобождается после flush и после отбрасывания буфера. Конечное состояние ресурса одинаково, состояние данных — нет. Наблюдение только за финалом теряет решение на ребре.

UNSELECT убрал неявное полномочие. Просьба освободить ресурс не даёт права окончательно удалить данные. Для необратимого шага клиент должен выбрать действие, которое прямо несёт этот смысл.

Источники