【问题标题】:Delphi XE2 - Unable to connect to Gmail smtp server via SSLDelphi XE2 - 无法通过 SSL 连接到 Gmail smtp 服务器
【发布时间】:2012-07-26 14:22:46
【问题描述】:

使用 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 组件运行良好。 Google Support

我们的 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;

【问题讨论】:

    标签: delphi ssl gmail openssl delphi-xe2


    【解决方案1】:

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

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

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

    【讨论】:

    • 嗯,UseTLS=utUseExplicitTLS 会这样做,但 UseTLS=utUseExplicitTLS 不会,其中一个是错误的
    • 最后一句中的UseTLS= 之一需要使用utUseImplicitTLS (隐式) - 他们都提到显式,还有一个其中显然是错误的。我怀疑它应该是utUseImplicitTLS 的第二个,但不确定是否足以编辑您的答案以进行更正。 :-)
    • 雷米,谢谢你的信息!你的解释很有道理,我明白现在发生了什么。
    • 在某个地方有显示所有这些的 Indy10 TLS/SSL+SMTP 演示应用程序吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 2014-03-31
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2017-10-09
    • 2015-06-13
    相关资源
    最近更新 更多