android - 套接字错误 110 : Connection Timed Out - Android Delphi SMTP Gmail

标签 android delphi smtp gmail

我正在使用 Delphi 为 Android 编写一个程序来发送包含数据的电子邮件。照原样,我的应用程序存在连接问题。

我有

  • 将主机设置为 smtp.gmail.com,

  • 输入我的 gmail 帐户的用户名和密码,

  • 为 TIdMessage 的地址和正文字段输入有效信息,

  • 制作并添加附件,

  • 根据在线示例为 TIdSSLIOHandlerSocketOpenSSL 设置 SSL 选项,并且

  • 添加了 Indy 提供的所有 SASL 机制。

我正在使用端口 587 并且已明确连接到 TLS。

type
  TForm1 = class(TForm)
    SendBtn: TButton;
    IdSMTP1: TIdSMTP;
    IdMessage1: TIdMessage;
    IdSASLAnonymous1: TIdSASLAnonymous;
    IdSASLCRAMMD51: TIdSASLCRAMMD5;
    IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
    IdSASLDigest1: TIdSASLDigest;
    IdSASLExternal1: TIdSASLExternal;
    IdSASLLogin1: TIdSASLLogin;
    IdSASLOTP1: TIdSASLOTP;
    IdSASLOTP2: TIdSASLOTP;
    IdSASLPlain1: TIdSASLPlain;
    IdSASLSKey1: TIdSASLSKey;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;

    procedure SendBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Attachment : TIdAttachmentFile;

implementation

{$R *.fmx}

procedure TForm1.FormCreate(Sender: TObject);
begin
  IdSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
  IdSMTP1.UseTLS := utUseExplicitTLS;
  IdSMTP1.AuthType := satSASL;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLDigest1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP2;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey1;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
end;

procedure TForm1.SendBtnClick(Sender: TObject);
begin
  if IdSMTP1.Connected=True then IdSMTP1.Disconnect;
  IdMessage1.From.Address := 'myemail@gmail.com';
  IdMessage1.Recipients.EMailAddresses := 'other@gmail.com';
  IdMessage1.BccList.Add.Address := '';
  IdMessage1.CCList.Add.Address := '';
  IdMessage1.Priority := mpHigh;
  IdMessage1.Sender.Address := 'myemail@gmail.com';
  IdMessage1.Subject := 'Test Data';   //Add Date/time
  IdMessage1.Body.Add('Hello!');
  Attachment := TIdAttachmentFile.Create(IdMessage1.MessageParts, (GethomePath+'/Test.txt'));
  IdSMTP1.Connect;
  IdSMTP1.Authenticate;
  IdSMTP1.Send(IdMessage1);
  IdSMTP1.Disconnect;
end;

失败于:

IdSMTP1.Connect;    

以这种方式连接到 Android 是否存在已知问题?

最佳答案

在这一行:

IdSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);

您正在创建并分配一个新的默认初始化的 SSLIOHandler,而不是使用表单上现有的 SSLIOHandler

该行应该是这样的:

IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;

事实上,您在 FormCreate() 中所做的一切都可以(并且应该)在设计时在窗体设计器中完成。您不需要在代码中执行此操作。

此外,我在您的表单上没有看到 TIdUserPassProvider。您使用的大多数 SASL 组件的用户名/密码都需要一个。 TIdSMTP.UserNameTIdSMTP.Password 属性仅在 AuthTypesatDefault 而不是 satSASL 时使用

除此之外,我建议对 SendBtnClick() 进行一些额外的更改:

  1. 您应该调用 IdMessage1.Clear(),这样您就不会携带以前发送的现有数据。您正在将新值附加到 IdMessage1.BccListIdMessage1.CCListIdMessage1.BodyIdMessage1.MessageParts无需先清除旧值。

  2. 您不需要调用 Authenticate()Send() 会在内部为您完成。

  3. Send() 应该在 try/finallytry/except block 中,这样你就可以调用 Disconnect () 即使 Send() 失败。

  4. 您没有正确配置 TIdMessage 以将文本和附件混合在一起。您应该TIdText 添加到 MessageParts 而不是使用 TIdMessage.Body(但是,如果 TIdMessage .ConvertPreamble 为真,如果存在任何附件,它将为您将 TIdMessage.Body 转换为 TIdText。但无论哪种方式,您都需要将 TIdMessage.ContentType 属性设置为 'multipart/mixed',以便接收方知道有多个 fragment 。

试试这个:

type
  TForm1 = class(TForm)
    SendBtn: TButton;
    IdSMTP1: TIdSMTP;
    IdMessage1: TIdMessage;
    IdSASLAnonymous1: TIdSASLAnonymous;
    IdSASLCRAMMD51: TIdSASLCRAMMD5;
    IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
    IdSASLDigest1: TIdSASLDigest;
    IdSASLExternal1: TIdSASLExternal;
    IdSASLLogin1: TIdSASLLogin;
    IdSASLOTP1: TIdSASLOTP;
    IdSASLOTP2: TIdSASLOTP;
    IdSASLPlain1: TIdSASLPlain;
    IdSASLSKey1: TIdSASLSKey;
    IdUserPassProvider1: TIdUserPassProvider;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;

    procedure SendBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // all of this code can be handled at design-time instead!

  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;

  IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
  IdSMTP1.UseTLS := utUseExplicitTLS;
  IdSMTP1.AuthType := satSASL;

  IdSASLCRAMSHA11.UserPassProvider := IdUserPassProvider1;
  IdSASLCRAMMD51.UserPassProvider := IdUserPassProvider1;
  IdSASLDigest1.UserPassProvider := IdUserPassProvider1;
  IdSASLLogin1.UserPassProvider := IdUserPassProvider1;
  IdSASLOTP1.UserPassProvider := IdUserPassProvider1;
  IdSASLOTP2.UserPassProvider := IdUserPassProvider1;
  IdSASLPlain1.UserPassProvider := IdUserPassProvider1;
  IdSASLSKey1.UserPassProvider := IdUserPassProvider1;

  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLDigest1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP2;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain1;
  IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey1;

  // end design-time capable hookups

  IdSMTP1.Host := ...;
  IdSMTP1.Port := ...;
  IdUserPassProvider1.UserName := ...;
  IdUserPassProvider1.Password := ...;
end;

procedure TForm1.SendBtnClick(Sender: TObject);
var
  Text: TIdText;
  Attachment : TIdAttachmentFile;
begin
  if IdSMTP1.Connected then IdSMTP1.Disconnect;

  IdMessage1.Clear;
  IdMessage1.From.Address := 'myemail@gmail.com';
  IdMessage1.Recipients.EMailAddresses := 'other@gmail.com';
  IdMessage1.Priority := mpHigh;
  IdMessage1.Sender.Address := 'myemail@gmail.com';
  IdMessage1.Subject := 'Test Data';   //Add Date/time
  //IdMessage1.Body.Add('Hello!');
  Text := TIdText.Create(IdMessage1.MessageParts);
  Text.ContentType := 'text/plain';
  Text.Body.Add('Hello!');
  Attachment := TIdAttachmentFile.Create(IdMessage1.MessageParts, (GethomePath+'/Test.txt'));
  IdMessage1.ContextType := 'multipart/mixed';             

  IdSMTP1.Connect;
  try
    IdSMTP1.Send(IdMessage1);
  finally
    IdSMTP1.Disconnect;
  end;
end;

关于android - 套接字错误 110 : Connection Timed Out - Android Delphi SMTP Gmail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37998891/

相关文章:

android - Dagger 2 : cannot be provided without an @Inject constructor or from an @Provides-annotated method

delphi - 如何更改 Delphi Firemonkey XE7 中 Stringgrid 标题的字体大小?

delphi - TVirtualStringTree 的 RootNode 的父级

delphi - 加快Delphi状态栏的更新速度

JavaMail - HELO 名称无效

java - 有没有使用 javamail 的通用实现来获取最后一个 SMTP 返回代码的标准方法

c++ - 使用 C++ WINSOCK(TCP、SSL)发送电子邮件

android - 自定义ActionBar形状android

具有 Activity android 的 Android 应用程序在启动时关闭

java - 如何在主类的对象上使用扩展类的方法? [JAVA]