2017-09-14 77 views
0

在將UseTLS設置爲utUseExplicitTLS並在其隱式TLS端口上連接到郵件服務器時,第一次嘗試允許連接併發送電子郵件,隨後在該端口上的嘗試正確失敗。在Delphi中使用Indy 10.6.2.5341的SMTP隱式TLS和顯式TLS

只是想知道如果任何人有任何想法如何避免在初始連接和發送誤報。

該檢查用於處理非標準端口可能正在用於用戶的郵件服務器。幾乎所有我見過的例子都假設總會提供正確的信息。

下面是處理它(不包括錯誤日誌)的代碼部分:

function SendTestEmail(EmailAddress: String): Boolean; 
var 
    EmailMessage: TidMessage; 
begin 
    IdSMTPEmail.AuthType := satDefault 
    IdSMTPEmail.Username := ...; 
    IdSMTPEmail.Password := ...; 
    IdSMTPEmail.Port := 465; 

    IdSMTPEmail.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTPEmail); 
    IdSMTPEmail.UseTLS := utUseExplicitTLS; 
    TIdSSLIOHandlerSocketOpenSSL(IdSMTPEmail.IOHandler).SSLOptions.Method := sslvTLSv1_2; 
    try 
    // Connect 
    IdSMTPEmail.Connect('smtp.gmail.com'); 

    try 
     // Create 
     EmailMessage := TidMessage.Create(nil); 

     try 
     // Set values 
     EmailMessage.Body.Add('Test Email'); 
     EmailMessage.Subject := 'Test Email'; 

     // Set sender details 
     EmailMessage.From.Address := '[email protected]'; 
     EmailMessage.From.Name := 'SSL Test'; 

     // Set recipient 
     EmailMessage.Recipients.Add.Address := EmailAddress; 

     try 
      // Send message 
      IdSMTPEmail.Send(EmailMessage); 

     except 
      // Exception 
      on E: EIdSMTPReplyError do 
      begin 
      // Result 
      Result := False; 
      end; 
     end; 

     finally 
     // Free email 
     EmailMessage.Free; 
     end; 

    finally 
     // Disconnect 
     IdSMTPEmail.Disconnect; 
    end; 

    except 
    // Exception 
    on E: Exception do 
    begin 
     IdSMTPEmail.Disconnect; 
     // Result 
     Result := False; 
    end; 
    end; 
end; 
+0

你所描述的是不可能的。隱式TLS端口要求在連接時立即啓動TLS握手,並在發送SMTP問候語之前完全完成TLS握手。 'utUseExplicitTLS'不會在連接時發送握手信號,所以'Connect()'將阻止等待一個永遠不會發送的問候,直到服務器斷開連接或經過'ReadTimeout'(以先發生者爲準)。無論哪種方式,調用代碼將無法發送足夠多的電子郵件。 –

+0

@RemyLebeau你說過的話是我期待的行爲,當上面的第一次嘗試工作時,它被驚呆了。作爲一個支票,我同時運行了Wireshark,它在第一次嘗試(也收到了電子郵件)中顯示成功,但隨後的嘗試超時並且Wireshark沒有收到任何內容。 – Aaron

+0

你說的根本不可能在**隱式TLS **端口上。 TLS握手是*必填*。您很可能在第一次嘗試時連接到*非隱式*端口,然後在隨後的嘗試中連接到*隱式*端口。使用Wireshark來驗證每個連接上使用的端口。 –

回答

0

使用下面的代碼,正確失敗的試圖通過電子郵件發送給端口465

我不所有的嘗試甚至假裝明白爲什麼這個作品,但我原來沒有。

function SendTestEmail(EmailAddress: String): Boolean; 
var 
    EmailMessage: TidMessage; 
    IdSSLHandler: TIdSSLIOHandlerSocketOpenSSL; 
begin 
    IdSMTPEmail.AuthType := satDefault; 

    IdSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create; 
    IdSSLHandler.SSLOptions.Method := sslvTLSv1_2; 

    IdSMTPEmail.IOHandler := IdSSLHandler; 
    IdSMTPEmail.UseTLS := utUseExplicitTLS; 

    IdSMTPEmail.Username := ...; 
    IdSMTPEmail.Password := ...; 
    IdSMTPEmail.Port := 465; 

    try 
    // Connect 
    IdSMTPEmail.Connect('smtp.gmail.com'); 

    try 
     // Create 
     EmailMessage := TidMessage.Create(nil); 

     try 
     // Set values 
     EmailMessage.Body.Add('Test Email'); 
     EmailMessage.Subject := 'Test Email'; 

     // Set sender details 
     EmailMessage.From.Address := '[email protected]'; 
     EmailMessage.From.Name := 'SSL Test'; 

     // Set recipient 
     EmailMessage.Recipients.Add.Address := EmailAddress; 

     try 
      // Send message 
      IdSMTPEmail.Send(EmailMessage); 

     except 
      // Exception 
      on E: EIdSMTPReplyError do 
      begin 
      // Result 
      Result := False; 
      end; 
     end; 

     finally 
     // Free email 
     EmailMessage.Free; 
     end; 

    finally 
     // Disconnect 
     IdSMTPEmail.Disconnect; 
    end; 

    except 
    // Exception 
    on E: Exception do 
    begin 
     IdSMTPEmail.Disconnect; 
     // Result 
     Result := False; 
    end; 
    end; 
end;