Кратко

  • UIDPLUS добавил к успешным APPEND и COPY значение UIDVALIDITY целевого ящика и назначенные сервером UID, позволив автономному клиенту сразу связать действие с его удалённым результатом.
  • Квитанция оставалась локальной: права доступа и UIDNOTSTICKY могли оправданно скрыть её, COPYUID не доказывал глобальную идентичность, а UID EXPUNGE удалял лишь указанные UID, уже помеченные \Deleted.

Короткое соединение требовало длинной памяти

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

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

RFC 2359 ввёл UIDPLUS в 1998 году как оптимизацию, особенно важную для отключающихся клиентов. Идея экономила не только сетевой обмен. Она позволяла закрыть локальную запись журнала фактом, полученным на границе успешной команды.

APPENDUID возвращал результат присвоения

APPENDUID помещается в тегированный OK успешного APPEND. В нём находятся UIDVALIDITY целевого ящика и UID новой записи. Локальный элемент очереди получает прямую удалённую ссылку без повторного выбора ящика и поиска по содержимому.

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

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

COPYUID фиксировал переименование при копировании

У копии в другом ящике появляется другой UID. COPYUID сообщает UIDVALIDITY назначения, набор исходных UID и набор целевых UID. Наборы обязаны иметь одинаковую мощность, а позиции задают пары.

Сходство значений не требуется. Сервер может сопоставить 304 с 3956, 319 с 3957 и 320 с 3958. Доказательство находится в ответе на конкретный COPY, а не в предположении клиента, что соседние письма с похожими заголовками совпадают.

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

Но область знания ограничена получателем ответа. RFC 8474 отмечает: другой клиент не может позже вывести ту же межъящичную связь из обычных UID. Для более широкой идентичности появились ObjectID. COPYUID — свидетельство одной мутации, а не универсальный паспорт письма.

UID EXPUNGE отделял свою волю от чужого флага

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

UID EXPUNGE принимает набор UID и действует только на пересечение двух условий. Сообщение должно входить в набор и уже иметь \Deleted. Названный UID без флага сохраняется; помеченное сообщение вне набора тоже сохраняется.

Так отключавшийся клиент мог завершить именно свои удаления, не превращая все чужие пометки в необратимый результат. На сервере без UIDPLUS запасной порядок требовал временно снять флаг с писем, которые нужно оставить, выполнить EXPUNGE и вернуть флаги. Это возможно, но затрагивает больше общего состояния.

Иногда отсутствие квитанции было правильным

Право APPEND или COPY не обязательно даёт право SELECT или EXAMINE целевого ящика. Возвращая его UIDVALIDITY и новый UID, сервер раскрыл бы сведения о хранилище, которое пользователь не вправе осматривать. RFC 4315 предписывает в такой ситуации не отправлять APPENDUID или COPYUID.

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

Нет кода — не значит нет успеха. Если права позволяют, клиент выбирает цель и ищет уникальную метку через FETCH или SEARCH. Этот обходной путь отделяет выполнение операции от видимости и устойчивости результата.

RFC 4315 исправил раннее обещание

В 2005 году RFC 4315 отменил RFC 2359. Он уточнил, что сервер не всегда обязан возвращать APPENDUID и COPYUID, описал UIDNOTSTICKY и закрепил правила множеств, нужные для добавления нескольких сообщений. Реестр IANA связывает UIDPLUS с новой спецификацией.

Позднее MOVE совместил создание в назначении с удалением в источнике. Если EXPUNGE приходил до COPYUID, видимые номера источника менялись раньше карты. RFC 6851 рекомендовал посылать COPYUID в нетегированном OK до сообщений об удалении; RFC 9051 включил этот порядок в IMAP4rev2.

История расширения показывает зрелость границ. Раннее желание всегда вернуть больше данных уступило правилу: вернуть полезное соответствие, если его раскрытие разрешено и имя способно сохранять смысл.

Проверяемость без универсальной гарантии

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

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

Источники и ограничения

Первое описание находится в RFC 2359, его заменила RFC 4315. Контекст IMAP4rev1 даёт RFC 3501, MOVE — RFC 6851, границу для других клиентов — RFC 8474, интеграцию IMAP4rev2 — RFC 9051. Реестр IANA содержит UIDPLUS. Источники не измеряют внедрение и не превращают UID в криптографическое доказательство, аутентификацию или подтверждение доставки.