Delphi XE2 - 无法通过SSL连接到Gmail smtp服务器

时间:2012-07-26 14:22:46

标签: delphi ssl gmail openssl delphi-xe2

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

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

到目前为止,我们已经解决了每个节目限制器,但我遇到了一个尝试连接到Gmail smtp服务器的插件。

我们的Delphi 6应用程序可以正常使用SSL v2.3和SSL v3以及连接到端口465的Indy 9组件(根据Google自己的文档)。 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连接&#39;配置。

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

我不知道为什么非TLS SSL选项不起作用,并且不报告任何错误,也没有超时但只是去永不落地。请帮忙!

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;

编辑:

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

如果我将UsetTLS属性设置为utUseImplicitTLS用于所有NON-SSL事务并将其设置为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;

1 个答案:

答案 0 :(得分:3)

你发现的是你应该做的事情。 SSL和TLS具有不同的语义,因此您必须相应地设置UseTLS

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

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