Кратко

  • После объявления PIPELINING в успешном ответе EHLO клиент мог отправить группу команд, не ожидая каждую реакцию, однако решения по командам не сливались.
  • Экономия задержки требовала позиционного счёта, границ состояния, правильной обработки многострочных ответов, учёта окна TCP и безусловного сохранения уже принятого ввода.

Платой было молчание

Обычная сессия SMTP чередует действие и ожидание: представиться, ждать; назвать отправителя, ждать; предложить получателя, ждать; запросить переход к данным и снова ждать. RFC 2920 отмечал, что на линиях с большой задержкой оборот каждого ответа мог определять всё время соединения.

Pipelining позволил известным командам уйти до возвращения первого ответа. Сервер по-прежнему судил каждую отдельно. Перекрывались паузы, а не полномочия решений.

Теперь одновременно оставалось несколько неподтверждённых намерений. В пошаговом режиме следующему ответу принадлежит один вопрос; в группе нужен точный порядок владельцев.

Реальный код потребовал явного объявления

TCP сохраняет порядок байтов, но развёрнутые серверы не всегда безопасно принимали опережающие строки. RFC 2920 перечисляет передачу соединения между процессами с потерей уже прочитанного буфера, очистку TCP-ввода после ошибки команды и неверную связь последнего RCPT TO с совокупным состоянием получателей и DATA.

Поэтому клиент сначала посылает EHLO и ждёт 250 с PIPELINING. Реестр расширений SMTP IANA по-прежнему связывает это слово без параметров с RFC 2920.

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

Изменение состояния завершало группу

RSET, команды отправителя и RCPT TO могут стоять внутри группы. EHLO, DATA, VRFY, EXPN, TURN, QUIT и NOOP должны быть последними, потому что их результат меняет дальнейшее состояние клиента. NOOP поэтому годится как точка синхронизации.

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

Ответу назначал владельца его номер

В условном примере отправитель, три получателя и DATA создают пять ожидаемых ответов. Коды могут повторяться, текст меняться. RFC 2920 прямо запрещает искать соответствие по коду или словам.

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

Ответ SMTP бывает многострочным. Промежуточная строка содержит дефис после кода, финальная — нет. Если принять строки за отдельные решения, вся последующая книга сдвинется. Содержание объясняет уже назначенный результат; оно не назначает владельца.

Порядок TCP не гарантировал движения

Неблокирующий клиент может читать ответы, пока предыдущая отправка ещё не завершена. Блокирующий клиент обязан убедиться, что вся группа помещается в окно TCP. Иначе он ждёт завершения записи, а сервер — чтения уже подготовленных ответов.

RFC 2920 исторически упоминал окно обычно, но не всегда, в 4K октетов. Это не универсальная современная настройка. Постоянное правило — согласовать группу с реальным потоком либо читать и писать одновременно.

PIPELINING увеличивает объём неподтверждённого намерения. Параллельность даёт производительность; доказуемый предел сохраняет продвижение.

Сервер обещал ничего не стирать

Объявивший способность сервер отвечает в порядке получения, не предполагает будущие команды и выпускает накопленные ответы, когда локальный TCP-буфер ввода опустел. Ни при каких условиях он не вправе очищать или терять его содержимое.

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

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

Документы сменились, правило осталось

RFC 1854 ввёл расширение в 1995 году. RFC 2197 заменил его в 1997-м, указав лишь редакционные изменения. RFC 2920 стал STD 60 в 2000 году. RFC 5321 всё ещё описывает SMTP как намеренно пошаговый диалог, изменяемый взаимно согласованным расширением.

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

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

Источники и пределы

История стандарта дана в RFC 1854, RFC 2197 и RFC 2920. Общий SMTP описывает RFC 5321, текущую запись — IANA. Они не измеряют нынешнее внедрение, настройки продуктов, выигрыш или частоту отказов.