【问题标题】:Delphi XE2 Indy 10.5.92 GMail SMTP error "Username and Password not accepted"Delphi XE2 Indy 10.5.92 GMail SMTP 错误“不接受用户名和密码”
【发布时间】:2014-11-26 06:43:11
【问题描述】:

我的问题是:为什么 gmail 给我这个错误:

不接受用户名和密码。了解更多信息 http://support.google.com/mail/bin/answer.py?answer=14257lp8sm18275694wic.17 - gsmtp

我尝试了一切,各种选项:SSL、TSL、SASL,但仍然没有。在某处我发现 google 需要一些 OAUTH2 SASL 方法,而这些方法将在 Indy 中完成。

当然,在 Delphi 6 和 Indy 9 上,在端口 465 上使用适当的 eay dll 并使用 ssl 可以正常工作。 有人知道该怎么做吗?

当然我安装了http://slproweb.com/products/Win32OpenSSL.html我有人问过...

代码如下:

procedure send(Recipientemail, AccountName, Pass, EmailSMTP,EmailPortNo :string);
var
  lTextPart: TIdText;
  lImagePart: TIdAttachmentfile;
  IdSMTP1: TIdSMTP;
  IdMsg: TIdMessage;
  SSLHandler:TIdSSLIOHandlerSocketOpenSSL;
  IdUserPassProv1: TIdUserPassProvider;

  IdSASLLogin1: TIdSASLLogin;
  IdSASLCRAMMD5: TIdSASLCRAMMD5;
  IdSASLCRAMSHA1: TIdSASLCRAMSHA1;
  IdSASLPlain: TIdSASLPlain;
  IdSASLLogin: TIdSASLLogin;
  IdSASLSKey: TIdSASLSKey;
  IdSASLOTP: TIdSASLOTP;
  IdSASLAnonymous: TIdSASLAnonymous;
  IdSASLExternal: TIdSASLExternal;
begin

  IdSMTP1:=TIdSMTP.Create(nil);
  IdMsg:=TIdMessage.Create(nil);
  IdSMTP1.Host:=EmailSMTP;
  IdSMTP1.Port:=EmailPortNo;
  //IdSMTP1.Username:=trim(AccountName);//tried with or without
  //IdSMTP1.Password:=trim(Pass);//tried with or without



    TIdSSLContext.Create.Free;
    SSLHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP1);
    SSLHandler.SSLOptions.Method := sslvSSLv3;
    SSLHandler.SSLOptions.Mode := sslmClient;
    IdSMTP1.IOHandler := SSLHandler;

    if (IdSMTP1.port = 465) then
        IdSMTP1.UseTLS := utUseImplicitTLS
      else
        IdSMTP1.UseTLS := utUseExplicitTLS;

    IdSASLLogin1:=TIdSASLLogin.Create(IdSMTP1);
    IdUserPassProv1:=TIdUserPassProvider.Create(IdSMTP1);
    IdUserPassProv1.Password:=trim(EmailHasloKonta);
    IdUserPassProv1.Username:=trim(EmailNazwaKonta);

    IdSMTP1.AuthType:=satSASL;

    IdSASLCRAMSHA1 := TIdSASLCRAMSHA1.Create(idSMTP1);
    IdSASLCRAMSHA1.UserPassProvider := IdUserPassProv1;
    IdSASLCRAMMD5 := TIdSASLCRAMMD5.Create(idSMTP1);
    IdSASLCRAMMD5.UserPassProvider := IdUserPassProv1;
    IdSASLSKey := TIdSASLSKey.Create(idSMTP1);
    IdSASLSKey.UserPassProvider := IdUserPassProv1;
    IdSASLOTP := TIdSASLOTP.Create(idSMTP1);
    IdSASLOTP.UserPassProvider := IdUserPassProv1;
    IdSASLAnonymous := TIdSASLAnonymous.Create(idSMTP1);
    IdSASLExternal := TIdSASLExternal.Create(idSMTP1);
    IdSASLLogin := TIdSASLLogin.Create(idSMTP1);
    IdSASLLogin1.UserPassProvider:=IdUserPassProv1;
    IdSASLPlain := TIdSASLPlain.Create(idSMTP1);
    IdSASLPlain.UserPassProvider := IdUserPassProv1;

    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA1;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD5;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
    IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain;

  IdMsg.CharSet:=CmbEncod.Text;
  IdMsg.From.Address:=EmailAdresNadawcy;
  IdMsg.From.Name:=ToISO_8859_2(true, EmailNadawca);

  IdMsg.Recipients.Add.Address:=email;
  if EmailDoWiad<>'' then IdMsg.BccList.Add.Address:=EmailDoWiad;

  IdMsg.ContentType:='multipart/relative';//; charset='+CmbEncod.Text;
  IdMsg.Subject:=ifthen(TytulEmaila='',translate('Potwierdzenie rezerwacji'),TytulEmaila);
  IdMsg.Body.Clear;
  IdMsg.Body.Text:='';

  lTextPart := TIdText.Create(IdMsg.MessageParts);
  lTextPart.Body.text:='Some body text';
  lTextPart.ContentType := 'text/plain';

  try
     IdSMTP1.Connect;     
     //IdSMTP1.Authenticate; //tried with or without

     try

      try
      IdSMTP1.Send(IdMsg);
      except
        on e: exception do
         MessageDlg('Sending error:'#13+
                  e.message,
                  mtinformation,[mbok],0);
      end;
     finally
        IdSMTP1.Disconnect;
     end;
   finally
     IdSMTP1.Disconnect;
     IdUserPassProv1.free;
     IdSASLLogin1.free;
     IdSASLCRAMMD5.free;
     IdSASLCRAMSHA1.free;
     IdSASLPlain.free;
     IdSASLLogin.free;
     IdSASLSKey.free;
     IdSASLOTP.free;
     IdSASLAnonymous.free;
     IdSASLExternal.free;
     lTextPart.Free;
     lImagePart.Free;
     SSLHandler.free;
     IdSMTP1.Free;
     IdMsg.Free;
     SSLHandler.Free;
   end;
end;

【问题讨论】:

    标签: delphi gmail delphi-xe2 indy10


    【解决方案1】:

    解决办法如下:

    在所有尝试之后似乎我有两个 dll libeay.dll 和 ssleay.dll 的错误版本。

    【讨论】:

      【解决方案2】:

      使用最新的 Indy 版本 (10.6.1),我可以使用 Indy 的 SASL 组件通过 SSL(端口 465 上的UseTLS=utUseImplicitTLS)和 TLS(端口 587 上的UseTLS=utUseExplicitTLS)成功地将 TIdSMTP 连接并验证到 Gmail使用与您显示的类似的代码。尽管普遍认为,OAUTH2 还不是必需的。

      您收到人类可读的身份验证错误这一事实意味着 SSL/TLS 部分工作正常,因此这严格来说是一个 SASL 问题。

      如果您的 Gmail 帐户使用两步验证,请确保您已在 Gmail 帐户设置中创建应用程序密码,您不能使用您的 Gmail 主密码。阅读 Gmail 的文档了解更多详情:

      Application-specific password required

      Sign in using App Passwords

      话虽如此,我建议您对显示的代码进行的唯一更改是:

      1. 设置UseTLS 属性可能会改变Port 属性值,因此您应该先设置UseTLS,然后再将Port 设置为所需的值:

        if (EmailPortNo = 465) then
          IdSMTP1.UseTLS := utUseImplicitTLS
        else
          IdSMTP1.UseTLS := utUseExplicitTLS;
        IdSMTP1.Port := EmailPortNo;
        
      2. 你不需要创建和销毁 TIdSSLContext 对象,所以摆脱它。手动创建TIdSSLContext 的唯一原因是它可以调用IdSSLOpenSSL.LoadOpenSSLLibrary() 函数,该函数是公共的,因此您可以在需要时直接调用它(在这种情况下实际上不需要)。

      3. multipart/relative 不是有效的 ContentType。你的意思是multipart/related 吗?您的 TIdMessage 不包含多个部分,因此您不应使用 multipart ContentType 开头。

      4. 您对Free() 的大部分调用都是多余的,因为您将TIdSMTP 指定为除TIdMessage 之外的所有内容的所有者。您不需要手动释放 SASL 组件,您可以让 TIdSMTP 为您完成。

      5. 你打电话给IdSMTP1.Disconnect() 两次。你不需要那个。

      【讨论】:

        猜你喜欢
        • 2020-09-29
        • 2018-05-30
        • 1970-01-01
        • 2023-04-08
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-13
        相关资源
        最近更新 更多