2015-10-09 8 views
0

У меня возникла очень странная проблема с отправкой писем через indy через два разных механизма в моей программе. Эта проблема аналогична [этой] [1], но не совсем то же самое. Я использую Indy 10.5 с последними библиотеками OpenSSL и Delphi XE3.Indy SMTP и Exchange Server

Первый фрагмент кода, который работает, является простым SMTP-клиентом, который я написал. Вот пример того, как я его настроил. Это не точный код, но он должен дать вам представление.

FIndySMTP.Intercept := FIndyLogFile; 
    FIndySMTP.IOHandler := FIndySSLHandler; 

    FIndyMessage.From.Address := FEmailAddress; 

    FIndySSLHandler.Destination := FSMTPAddress + ':' + IntToStr(FSMTPPort); 
    FIndySSLHandler.Host := FSMTPAddress; 
    FIndySSLHandler.Port := FSMTPPort; 
    FIndySMTP.Host := FSMTPAddress; 
    FIndySMTP.Port := FSMTPPort; 
    FIndySMTP.Username := FAccountName; 
    FIndySMTP.Password := FAccountPass; 
    FIndySMTP.AuthType := satDefault; 
    FIndySMTP.UseEhlo := True; 
    FIndySMTP.UseTLS := utUseExplicitTLS 

    FIndySMTP.Connect; 
    try 
    if FIndySMTP.Connected = True then 
     FIndySMTP.Send(FIndyMessage); 
    finally 
    FIndySMTP.Disconnect; 
    end; 

Это создает успешную почту с журналом:

Recv 10/9/2015 10:41:02 AM: 220 server.server1.local Microsoft ESMTP MAIL Service ready at Fri, 9 Oct 2015 13:41:01 -0400<EOL> 
Sent 10/9/2015 10:41:02 AM: EHLO DEIMOS<EOL> 
Recv 10/9/2015 10:41:02 AM: 250-server.server1.local Hello [68.14.239.173]<EOL>250-SIZE 36700160<EOL>250-PIPELINING<EOL>250-DSN<EOL>250-ENHANCEDSTATUSCODES<EOL>250-AUTH<EOL>250-8BITMIME<EOL>250-BINARYMIME<EOL>250 CHUNKING<EOL> 
Sent 10/9/2015 10:41:02 AM: RSET<EOL> 
Recv 10/9/2015 10:41:02 AM: 250 2.0.0 Resetting<EOL> 
....(The rest snipped) 

Теперь второй метод, который использует Report Builder, построенный в компонентах электронной почты для отправки отчета по электронной почте (опять же, некоторый код отрезало для краткость, реальный ключ находится в логах):

lIOHandler.Destination := Host + ':' + IntToStr(Port); 
    lIOHandler.Host := Host; 
    lIOHandler.Port := Port; 

    TheReport.EmailSettings.HostAddress := Host; 
    TheReport.EmailSettings.UserName := UserName; 
    TheReport.EmailSettings.Password := Password; 
    lEmail.SMTP.OnEmailError := FMain.EmailErrorEvent; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.OnFailedRecipient := FMain.idSMTPFailedRecipient; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.Intercept := FMain.IdLogFile1; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.Port := Port; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.IOHandler := lIOHandler; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.UseTLS := utUseExplicitTLS; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.AuthType := satDefault; 
    TppSMTPIndy(lEmail.SMTP).IndySMTP.UseEhlo := True; 

    TheReport.SendMail; 

Вы можете увидеть, что за исключением использования построителя отчетов TppSMTPIndy, каждая установка та же. Тем не менее, электронная почта не посылают, а журнал выглядит следующим образом:

Stat Connected. 
Recv 10/9/2015 10:44:31 AM: 220 server.server1.local Microsoft ESMTP MAIL Service ready at Fri, 9 Oct 2015 13:44:28 -0400<EOL> 
Sent 10/9/2015 10:44:31 AM: EHLO DEIMOS<EOL> 
Recv 10/9/2015 10:44:31 AM: 250-server.server1.local Hello [68.14.239.173]<EOL>250-SIZE 36700160<EOL>250-PIPELINING<EOL>250-DSN<EOL>250-ENHANCEDSTATUSCODES<EOL>250-AUTH<EOL>250-8BITMIME<EOL>250-BINARYMIME<EOL>250 CHUNKING<EOL> 
Sent 10/9/2015 10:44:31 AM: QUIT<EOL> 
Recv 10/9/2015 10:44:31 AM: 221 2.0.0 Service closing transmission channel<EOL> 
Stat Disconnected. 

Вы можете видеть, что QUIT отправляется сразу после получения ПРИВЕТ. Вот почему мой вопрос отличается от ссылки выше. Этот человек, по крайней мере, получил запрос STARTTLS.

Что может заставить Indy отправить QUIT сразу после получения HELLO? Я не получаю никаких ошибок. Он просто не работает, и программа движется дальше.

Теперь вот подсказка кикера. Если я установлю AuthType на satNone в примере построителя отчетов, он работает. Хотя в моем первом примере я могу установить AuthType для satNone и satDefault, и оба они работают.

Любые идеи?

Большое спасибо за ваше время.

+0

Вы забыли указать URL-адрес ссылки «этот». –

ответ

3

Что может заставить Indy отправить QUIT сразу после получения HELLO?

Единственный раз, когда QUIT отправляется, когда вызывается TIdSMTP.Disconnect().

Единственный раз, что TIdSMTP сам называет Disconnect() это когда:

  1. исключение возникает внутри TIdSMTP.Connect(), например, если приветствие сервера имеет код ошибки, или есть неожиданная проблема разборе сервера приветствие или ответ EHLO.

  2. исключение создается внутри TIdSMTP.StartTLS(), который вызывается TIdSMTP.Authenticate() (который вызывается TIdSMTP.Send(), если он еще не вызван заранее). Однако, поскольку вы установили UseTLS=utUseExplicitTLS, а ответ сервера EHLO не поддерживает рекламу для STARTTLS, TIdSMTP.StartTLS() фактически не работает на этом сервере.

Я не получаю никаких ошибок.Он просто не работает, и программа движется дальше.

Если построитель отчетов не догоняет исключения внутренне и не передавая их в код, то наиболее вероятным сценарием является то, что Report Builder сам звонит TIdSMTP.Disconnect() без вызова TIdSMTP.Send() первым. Команда RSET, указанная в вашем журнале, отправляется TIdSMTP.Send() в начале сообщения электронной почты (BTW, более поздние версии Indy больше не отправляют RSET, если сообщение электронной почты не с кодом ошибки SMTP). Построитель отчетов, вероятно, просто пропускает Send(), и я могу думать о одной возможной причине, почему он может это сделать.

AuthType=satDefault использует AUTH LOGIN команду (которая не является безопасной командой), но EHLO реакции вашего сервера не является рекламой поддержки LOGIN аутентификации (на самом деле, это не рекламой поддержки любых аутентификации на всех). Таким образом, TIdSMTP.Authenticate() будет пропускать аутентификацию на этом сервере по умолчанию и вернуть False, а также установить для свойства TIdSMTP.DidAuthenticate значение False. Возможно, Report Builder напрямую вызывает TIdSMTP.Authenticate() и проверяет результат перед вызовом TIdSMTP.Send(). Ваш пример, отличный от ReportBuilder, не выполняет эту проверку. Установка AuthType=satNone приведет к возврату TIdSMTP.Authenticate() и установите для свойства TIdSMTP.DidAuthenticate значение True.

Если сервер происходит для поддержки LOGIN аутентификации (некоторые серверы поддерживают это не афишируя этого), вы можете установить TIdSMTP.ValidateAuthLoginCapability свойство Ложные (оно истинно по умолчанию), чтобы сделать аутентификацию satDefault попытку, пока TIdSMTP.Username Свойству была присвоена непустая строка.

+0

Я проверил исходный код Report-Builder, и они фактически вызывают TidSMTP.Authenticate() и проверяют результат перед вызовом TidSMTP.Send(). У меня есть электронное письмо с человеком, который управляет сервером обмена. Я буду держать вас в курсе. Спасибо Реми. – FLDelphi

 Смежные вопросы

  • Нет связанных вопросов^_^