2

使用 Delphi XE2、随附的 Indy 10 和 OpenSSL dll 的 1.0.1c 版本。

我们正处于将 Delphi 6 项目转换为 Delphi XE2 的最后阶段。

到目前为止,我们已经解决了所有问题,但我遇到了一个尝试连接到 Gmail smtp 服务器的问题。

根据 Google 自己的文档,我们的 Delphi 6 应用程序使用 SSL v2.3 和 SSL v3 以及连接到端口 465 的 Indy 9 组件运行良好。谷歌支持

我们的 Delphi XE2 应用程序根本无法连接。连接的调用进入以太,大约 7 分钟没有任何反应,直到我厌倦了等待事情超时并将其杀死。实际上,我在这里一直跟踪程序执行到 IdWinsock2 函数:

function Stub_select(nfds: Integer; readfds, writefds, exceptfds: PFDSet; timeout: PTimeVal): Integer; stdcall;
begin
  @select := FixupStub(hWinSockDll, 'select'); {Do not Localize}
  Result := select(nfds, readfds, writefds, exceptfds, timeout);//<-this line never returns and timeout is always nil
end;

我需要为现有用户的配置维护旧的 SSL 连接。

新用户将能够使用 TLS(连接到端口 587)进行连接,并且可以正常工作!?!?

我不知道为什么非 TLS SSL 选项不起作用,也没有报告任何错误,也没有超时,只是去 Never-Never Land。请帮忙!

TJ

这是代码:

  SMTPClient.Host := trim(EditSMTPServer.Text);
  SMTPClient.Port := EditSMTPServerPort.AsInteger;//<- value from custom edit box
  SMTPClient.Username := trim(EditSMTPLogon.Text);
  SMTPClient.Password := trim(EditSMTPPassword.Text);
  SMTPClient.AuthType := satDefault;

  if CheckBoxUseSSL.Checked then begin
    SMTPClient.IOHandler := IdSSLIOHandlerSocket1;
    IdSSLIOHandlerSocket1.ReadTimeout := 30000;//30 second timeout which does not appear to work
    case ComboBoxSSLMode.ItemIndex of
      0 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv2;
      1 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23;
      2 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv3;
      3 : begin
        IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLsv1;
        SMTPClient.UseTLS := utUseImplicitTLS;
      end;
    end;//case
    IdSSLIOHandlerSocket2.SSLOptions.Method := IdSSLIOHandlerSocket1.SSLOptions.Method;
    IdSSLIOHandlerSocket2.PassThrough := False;
  end
  else begin
    SMTPClient.IOHandler := nil;
  end;

  try
    SMTPClient.Connect;
    if SMTPClient.Connected then begin
      if SMTPClient.Authenticate then begin
      ... do some work ...
      end;
    end;
  except
    on e:Exception do begin
      showmessage(e.message);
    end;
  end;

编辑:

像往常一样,在我发布问题后,我偶然发现了一种解决方法。

如果我将所有非 SSL 事务的 UsetTLS 属性设置为 utUseImplicitTLS 并将其设置为 utUseExplicitTLS 以进行 TLS 事务,我的连接似乎可以及时工作。

希望这可以帮助某人。

更新代码:

if CheckBoxUseSSL.Checked then begin
  SMTPClient.IOHandler := IdSSLIOHandlerSocket1;
  SMTPClient.UseTLS := utUseImplicitTLS;
  case ComboBoxSSLMode.ItemIndex of
    0 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv2;
    1 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23;
    2 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv3;
    3 : begin
      IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLsv1;
      SMTPClient.UseTLS := utUseExplicitTLS;
    end;
  end;//case
  IdSSLIOHandlerSocket2.SSLOptions.Method := IdSSLIOHandlerSocket1.SSLOptions.Method;
  IdSSLIOHandlerSocket2.PassThrough := False;
end
else begin
  SMTPClient.UseTLS := utNoTLSSupport;//reset TLS support flag
  SMTPClient.IOHandler := nil;
end;
4

1 回答 1

3

你发现的就是你应该做的。SSL 和 TLS 有不同的语义,所以你必须进行UseTLS相应的设置。

对于端口 465 上的 SSL,服务器希望您的客户端在连接后立即启动 SSL 握手,然后服务器发送加密的问候语。 UseTLS=utUseImplicitTLS这样做,但UseTLS=utUseExplicitTLS没有。当UseTLS=utUseExplicitTLS,TIdSMTP将期望服务器立即发送未加密的问候语,这将解释挂起select()- 服务器没有发送任何数据!

对于端口 587 上的 TLS,服务器期望客户端最初连接时未加密,然后STARTTLS在准备好启动加密时发送显式命令。 UseTLS=utUseExplicitTLS这样做,但UseTLS=utUseImplicitTLS没有。

于 2012-07-26T20:29:12.687 回答