2

Delphi XE2、同梱のIndy 10、およびOpenSSLdllのバージョン1.0.1cを使用します。

現在、Delphi6プロジェクトをDelphiXE2に変換する最終段階にあります。

これまでにすべてのショーストッパーを解決しましたが、GmailのSMTPサーバーに接続しようとしています。

GoogleのDelphi6アプリは、SSLv2.3とSSLv3、およびGoogle独自のドキュメントに従ってポート465に接続するIndy9コンポーネントを使用して正常に動作します。Googleサポート

DelphiXE2アプリはまったく接続しません。接続するための呼び出しはエーテルに入り、物事がタイムアウトしてそれを殺すのを待つのに飽きるまで、約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に)接続できるようになり、それは機能します!?!?

非TLSSSLオプションが機能せず、エラーを報告せず、タイムアウトせず、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に設定し、TLSトランザクションに対してutUseExplicitTLSに設定すると、接続がタイムリーに機能しているように見えます。

うまくいけば、これは誰かを助けるでしょう。

更新されたコード:

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=utUseExplicitTLSTIdSMTPサーバーは暗号化されていないグリーティングをすぐに送信することを期待します。これは、ハングインを説明しますselect()-サーバーはデータを送信していません!

STARTTLSポート587のTLSの場合、サーバーは、クライアントが最初は暗号化されていない状態で接続し、暗号化を開始する準備ができたら明示的なコマンド を送信することを期待しています。UseTLS=utUseExplicitTLSそれをしますが、UseTLS=utUseImplicitTLSしません。

于 2012-07-26T20:29:12.687 に答える