Re: Re: connection is broken - держаться больше нету сил!

От: Vladimir A. Butenko <CGatePro_at_mx_ru>
Дата: Sat 24 Dec 2005 - 17:48:20 MSK

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

On Sat, 24 Dec 2005 15:33:17 +0300
  "Maxim Cherniavsky" <CGatePro@mx.ru> wrote:

> Iliya Peregoudov wrote:
> 

>> Maxim Cherniavsky wrote:
>>
>>>>>
>>>>> Т.е приходит подряд два ответа, что на мой вгляд ничему не
>>>>> противоречит (rfc 2821)
>>>>>
>>>>> An SMTP server MUST NOT intentionally close the connection except:
>>>>>
>>>>> - After receiving a QUIT command and responding with a 221 reply.
>>>>>
>>>>> - After detecting the need to shut down the SMTP service and
>>>>> returning a 421 response code. This response code can be issued
>>>>> after the server receives any command or, if necessary,
>>>>> asynchronously from command receipt (on the assumption that the
>>>>> client will receive it after the next command is issued).
>>>>> ключевое слово asynchronously что на самом деле и происходит, и по
>>>>> логам CGP мы видим как будто 421 вернулся на RSET, что на самом
>>>>> деле не так.
>>>>
>>>>
>>>> Вчитайтесь внимательнее. Это как раз тот самый пример, мягко говоря,
>>>> неквалифицировнности - у авторов всяко разных "расширений протоколов".
>>>
>>>
>>> Ну какое расширение то? В 821ой тоже было про 421 вообще на любую
>>> команду, в разделе sequence of commands
>>>
>>
>> На стр. 36 [RFC822] написано:
>>
>> 421 <domain> Service not available, closing transmission channel
>> [This may be a reply to any command if the service knows it must shut
>> down]
>>
>> На стр. 37 [RFC822] (SEQUENCING OF COMMANDS AND REPLIES) написано:
>>
>> The communication between the sender and receiver is intended to be an
>> alternating dialogue, controlled by the sender. As such, the sender
>> issues a command and the receiver responds with a reply. The sender
>> must wait for this response before sending further commands.
>>
>> Т.е. автор RFC822 понимал (конечно, понимал, на то он и Postel), что у
>> любого протокола стоит задача корреляции запроса с ответом. Вот про
>> это и комментарий со стр. 37: SMTP -- чёткий диалог, причём сервер в
>> нём -- пассивная сторона. И отвечать сервер должен одним ответом на
>> один запрос. Если уж так хочется ответить 421, будь добр дождаться
>> запроса.
>> Но не любого, поскольку на QUIT и TURN отвечать 421 нельзя (согласно
>> стр. 38).
> 
> Да, в 821 было четко прописано на какую команду какие ответы. Но этого нет 
>в 2821, может я что то и просмотрел

Нету. И это проблема г-на Кленсина, который ни малейшего отношения к этим протоколам не имеет, но решил увековечить своё имя, став Editor (хорошо хоть, что не author) этого 2821.

Но сути это не меняет: сути протокола SMTP, которые есть клиент-сервер без МАЛЕЙШЕЙ асинхронности. И далее Вам об"ясняют, почему:

>> Почему так важна чёткая корреляция запросов с ответами? Пример:
>>
>> C: MAIL, RCPT, RCPT
>> S: 250, 451, 421
>>
>> Какой из адресов-реципиентов отлупляет сервер своим третьим ответом?
>> По привычной логике -- второго, и тут привычная логика совпадает с
>> RFC822. По логике RFC2822 -- первого.

> 
> 
> Согласен, но результат доставки то все равно один - письмо не прошло, тем 
>более что второй RCPT вы сказали в закрытый сокет

Нет, результат РАЗНЫЙ.
Во-первых "сказали в закрытый сокет" - Вы совсем неправы. Если коннект закрывался сервером при помощи FIN, то клиент об этом узнает, только почитав с сокета что-то. Например, когда Вы делаете FTP трансвер на сервер, то сервер, открыв с Вами data connection, сразу же может выдать close() на свою часть сокета (shutdown по униксному), и потом - принять от Вам 10GB файл, зато когда Ваш конец пошлёт FIN, то соединение закроется мгновенно. Так вот, выдав второй RCPT To, cервер не только не обнаружит того, что другой конец "закрыт", он и при чтении этого не обнаружит. Сначала он обнаружит там 421 - неважно, выдал ли сервер этот ответ сейчас, или послал его "асинхронно" 5 минут назад: сам протокол сугубо синхронный. И этот 421 будет считан и интерпретирован как отлуп второго адреса RCPT. И этот адрес будет, в соответствии, с настройками Вашего сервера, отложен на какое-то время. А первый адрес - на другое (если Ваш сервер различает 450 и 421). А потом, выдав СЛЕДУЮЩУЮ команду - RSET, DATA, RCPT TO - сервер увидит FIN - "connection is broken" - и уже отложит очередь всего хоста. На какое-то третье время.

Я надеюсь, теперь Вам стало понятно, почему выдавать ДВА ответа на один запрос сервера (450 и 421) - это глупость: двух ответов быть не может, второй ответ будет воспринят как ответ на СЛЕДУЮЩУЮ команду. И этот ответ будет воспринят совсем по-другому: 4xx в ответ на RCPT TO, MAIL FROM, на DATA, на ".", и на любую другую команду воспринимается ПО РАЗНОМУ: первое - откладывает доставку данного письма на данный адрес, второе-четвертое - откладывает доставку данного письма на все адреса выданные выше, остальное - сигнализирует о проблеме всего сервера, и, соответственно, откладывает всю очередь на сервер.

Когда Вы говорите, что по приему 421 на RSET CGatePro должен отложить не очередь на хост, а "только письмо", то Вы не учитываете того, что "текужего" письма уже нет. Выдав RSET CGatePro привел сессию в исходное состояние - ни на одном конце нету никакого письма "в процессе обработки". Более того, письмо в CGatePro (точнее, "batch" - совокупность письма и набора адресов внутри данного хоста) - уже "released" и возвернут в очередь хоста как "незанятый". Далее, если у Вас в этот момент шла параллельная посылка на этот хост в несколько каналов, то письмо могло быть схвачено другим каналом и уже доставлено им (обычно так не происходит, потому что batch был всё же отложен, но если на 4xx Вы откладываете адреса на 0 секунд - то запросто).

Надеюсь, что теперь мы разобрались с разницей в ответах "отлуп на письмо", "отлуп на адрес", и "отлуп на разговор".

> С помощью 421 сервер не отлупляет адрес ресипиента, он отлупляет текущую 
>транзакцию, rollback так сказать, а последний 250 queued был промежуточным 
>commit'ом.

Это классно, только не имеет никакого отношения к протоколу SMTP. По поводу асинхронности - она таки есть. Но совершенно в другом смысле. Она означает, что если Вы знаете ЧТО нужно выдать в ответ на следующую команду, то Вы можете это выдать сразу. Например, Вы, найдя спам в письме на этапе приема - можете выдать 4xx сразу, не дожидаясь ".". Но если при этом вы бросите канал (да еще не FIN'ом, а RESET-ом), то не надейтесь, что Ваш 4хх кто либо получит - получат "connection is broken", и опять же отложат-отлупят не письмо, а всю очередь на Ваш хост.

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

5xx а пошёл ты!
5xx а пошёл ты!
5xx а пошёл ты!
5xx а пошёл ты!
5xx а пошёл ты!
5xx а пошёл ты!
5xx а пошёл ты!

Но опять же - плавно и культурно закрыть соединение.

В обратную сторону асинхронность используется чаще. Можно в сервер выдать сразу кучу RCPT TO:, а потом - разгребать ответы на них. По хорошему, для того, чтобы так делать, клиент обязан проверить, что сервер выдал PIPELINING в числе своих свойств (смысл - позволить работать таким дремучим хостам, у которых TCP не поддерживает flow control - вряд ли таковые есть).   

>> На самом деле, не так уж важно, закрыл сервер сессию молча, или плюнул
>> перед этим 421, он её закрыл. Причём не по команде клиента. И клиент
>> это должен расценивать однозначно -- сервер не хочет с ним говорить,
>> зазорным считает.

>
> Не хочет и считает зазорным в рамках ДАННОЙ сессии.

Да. А что такое "сессия"? И чем она отличается от "другой сессии"? В тот момент, когда "активного письма" в ней нет? А даже если есть?

>> В вашем случае надо просто добиться того, чтобы SMTP сервер не
>> закрывал сессию.

> 
> Я не согласен что это надо решать такими методами, почему неправильно 
>открыть новую сессию и пытаться доставить следующее письмо?

Потому что если у меня нормальный сервер, то он бросит соединение с Вами тогда, когда он не хочет разговаривать С ВАМИ. А если Вы будете после этого непрерывно долбиться, то он (сервер) позвонит в Спортлото и будет требовать Вашей экстрадиции.

>То письмо на 
>котором пришло 421 (или еще какое нарушение протокола) откладывается с 
>соответствующим delay и все. Основная мысль, которую я высказываю - не надо 
>банить весь сервер, от этого гораздо больше вреда, чем пользы.

А Вам тщательно и повторно об"ясняют, что если 4xx пришло "на письмо", то отложится само письмо. А если пришло не на письмо, но отложится сервер.   

>>
>> Если SMTP сервер закрывает сессию из-за того, что в сессии слишком
>> много отлупов, надо найти способ заставить клиент организовывать
>> сессии покороче. Есть ли в CGP настройки для ограничения количества
>> MAIL/RCPT, выдаваемых в одной сессии?
>
> Я вроде не видел....

Вы знаете, если Вы помимо приведения выдержек из Логов, попробуете еще открывать настройки сервера (об открывании мануала я и не мечтаю уже) - то сеттинг Recipients/Message наверняка приведет к еще более глубокому удивлению.   

>> Если SMTP сервер закрывает сессию из-за того, что словил 1 письмо с
>> вирусом, в топку такой сервер. Если же он делает это только после
>> ловли N писем с вирусами в одной сесии -- решение опять же в
>> укорочении сессий с этим сервером.

> 
> С почтой последние N лет все достаточно печально и среда сильно агресивна, 
>поэтому лучше потратить чуть больше ресурсов, но письмо таки доставить.

А оно и будет доставлено. На нормально работающий сервер.

> -- 
> Best regards,
>                                         Maxim Cherniavsky
>                                         Comstar-UTS, Internet Division
>                                         mailto: maxim (at) comstar.ru 

Sincerely,
Vladimir Получено Sat Dec 24 14:48:17 2005

Этот архив был сгенерирован hypermail 2.1.8 : Tue 21 Feb 2006 - 03:17:58 MSK