套接字错误110:连接超时-Android Delphi SMTP Gmail

套接字错误110:连接超时-Android Delphi SMTP Gmail,android,delphi,smtp,gmail,Android,Delphi,Smtp,Gmail,我正在为Android编写一个程序,使用Delphi发送一封包含数据的电子邮件。目前,我的应用程序存在连接问题 我有 将主机设置为smtp.gmail.com 输入我的gmail帐户的用户名和密码 为消息的地址和正文字段输入有效信息 制作并添加了一个附件文件 根据联机示例设置TIdSSLIOHandlerSocketOpenSSL的SSL选项,以及 添加了所有的SASL机制Indy提供 我正在使用端口587,并已明确连接到TLS type TForm1 = class(TForm)

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

我有

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

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

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

  • 制作并添加了一个附件文件

  • 根据联机示例设置TIdSSLIOHandlerSocketOpenSSL的SSL选项,以及

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

我正在使用端口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;
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;
事实上,您在
FormCreate()
中所做的一切都可以(也应该)在设计时在表单设计器中完成。你不需要用代码来做

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

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

  • 您应该调用
    IdMessage1.Clear()
    ,这样就不会从以前的发送中携带现有数据。您正在向
    IdMessage1.BccList
    IdMessage1.CCList
    IdMessage1.Body
    IdMessage1.MessageParts
    添加新值,而不首先清除旧值

  • 您不需要调用
    Authenticate()
    Send()
    在内部为您这样做

  • Send()
    应该在
    try/finally
    try/except
    块中,这样即使
    Send()
    失败,也可以调用
    Disconnect()

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

  • 请尝试以下方法:

    IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
    
    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;
    

    那是一个非常彻底的回答!非常感谢你的帮助。但是,这不允许我的应用程序实际发送电子邮件。我收到一个错误,说是通过我的网络浏览器登录,还有一封来自谷歌的电子邮件说一个没有足够安全性的应用程序试图访问我的帐户。你有没有想过如何避开这个问题?我认为我们使用TLS符合安全标准。再次感谢!您没有收到TLS错误,您收到的是身份验证错误。加密(套接字传输的安全性)和身份验证(你的谷歌身份)是两件不同的事情。你需要进入你的谷歌账户,1)启用,然后Indy可以使用你的普通谷歌密码登录;2) 打开两步验证,然后生成一个供Indy使用的密码,而不是您的普通密码。此时,Indy没有实现OAuth,特别是在SASL上(尽管我认为可能会有一些第三方实现),这就是为什么
    tidmtp
    不能使用普通的谷歌密码登录,除非你降低谷歌安全设置,或者只为Indy生成一个单独的密码。哇!这太棒了!这很有趣,很高兴知道。但是附件不是这样工作的。单击“发送”按钮时,程序将挂起,但当有关附件的两行被注释掉时,程序将运行。@DelphiAndroid12:我无法回答这个问题。您必须自己调试它,并找出实际冻结的内容。文件存在吗?你确定你正在使用它的当前路径吗?您有权限访问该文件吗?在任何情况下,您都不应该在主UI线程中执行阻塞操作,尤其是在Android上(这可能会杀死您的应用!)。您的按钮启动一个工作线程来处理在UI线程之外发送的电子邮件。