在vps计算机内执行时,IdSMTP无法发送电子邮件

时间:2018-02-08 16:17:17

标签: delphi indy

我想发送电子邮件 Hotmail > Gmail ,其中包含附件文件,我在下面安装了此代码,并且在我自己的计算机上执行时工作正常,已经在vps计算机内执行时不发送任何消息。

/////////////////////////////////////////////// /

这段代码有什么问题?

uses
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase,
  IdMessageClient, IdSMTPBase, IdSMTP, IdMessage, IdAttachmentFile,
  IdSSLOpenSSL, IdGlobal;

procedure SendEmail(const Attach, Recipients: string; const Subject: string; const Body: string);
var
  SMTP: TIdSMTP;
  Email: TIdMessage;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin

  try

    SMTP := TIdSMTP.Create(nil);
    Email := TIdMessage.Create(nil);
    SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

    SSLHandler.MaxLineAction := maException;
    SSLHandler.SSLOptions.Method := sslvTLSv1;
    SSLHandler.SSLOptions.Mode := sslmUnassigned;
    SSLHandler.SSLOptions.VerifyMode := [];
    SSLHandler.SSLOptions.VerifyDepth := 0;

    SMTP.AuthType := satDefault;
    SMTP.IOHandler := SSLHandler;
    SMTP.Host := 'smtp.live.com';
    SMTP.Port := 587;
    SMTP.Username := 'test@hotmail.com';
    SMTP.Password := 'test123';
    SMTP.UseTLS := utUseExplicitTLS;

    Email.From.Address := 'test@hotmail.com';
    Email.From.Name := 'TEST';
    Email.Recipients.EmailAddresses := Recipients;
    Email.Subject := Subject;
    Email.Body.Text := Body;

    if not FileExists(Attach) then
      Exit;

    TIdAttachmentFile.Create(Email.MessageParts, Attach);

    try

      SMTP.Connect;
      SMTP.Send(Email);
      SMTP.Disconnect;

    except
      Exit;
    end;

  finally
    SMTP.Free;
    Email.Free;
    SSLHandler.Free;
  end;
end;

SendEmail('c:\test.txt', 'recipient@gmail.com', 'Test SUBJECT', 'Test Body');

版:

错误是:

  

身份验证失败

enter image description here

    try
      SMTP.Connect;
      SMTP.Authenticate;
    except
      on E:Exception do
      begin
        MessageDlg('' +
          E.Message, mtWarning, [mbOK], 0);
        Exit;
      end;
    end;

    try
      SMTP.Send(Email);
      MessageDlg('Sent!', mtInformation, [mbOK], 0);
    except
      On E:Exception do
      begin
        MessageDlg('' +
          E.Message, mtWarning, [mbOK], 0);
      end;
    end;

  finally
    SMTP.Disconnect;
    SMTP.Free;
    Email.Free;
    SSLHandler.Free;
  end;

1 个答案:

答案 0 :(得分:4)

从错误消息中可以清楚地看出,服务器在发送电子邮件之前拒绝了您的身份验证尝试。

在我详细介绍您的问题之前,让我向您提供一些信息,以便了解TIdSMTP身份验证的一般情况。

默认情况下,TIdSMTP.AuthType属性为satDefaultTIdSMTP.ValidateAuthLoginCapability属性为True。这意味着TIdSMTP.UsernameTIdSMTP.Password属性是使用不安全的AUTH LOGIN命令发送的(大多数服务器在没有建立SSL / TLS会话的情况下都不会接受),但仅限于服务器的{{1}回复表明EHLO是可接受的身份验证(许多服务器都不会报告,即使他们确实接受了它)。

因此,LOGIN(您不需要手动调用,TIdSMTP.Authenticate()为您调用它)可能甚至无法在TIdSMTP.Send()时尝试向服务器进行身份验证,然后对AuthType=satDefault的后续调用可能会因身份验证错误而失败(您可以通过将Indy的TIdSMTP.Send()组件之一分配给TIdLog...属性来验证这一点,然后查看实际的SMTP命令TIdSMTP.Intercept发送)。

因此,请尝试将TIdSMTP设置为False,以便TIdSMTP.ValidateAuthLoginCapabilityTIdSMTP.Authenticate()时始终发送AUTH LOGIN,无论服务器是否报告可接受。如果服务器不接受它,那么至少它将在该阶段而不是AuthType=satDefault阶段验证失败。

但是,现在大多数SMTP服务器都接受/需要比Send()更强的身份验证方案,例如LOGINCRAM-SHA1。因此,您可以设置CRAM-MD5,然后使用相关的AuthType=satSASL派生组件填充TIdSMTP.SASLMechanisms集合(包括TIdSASL以便在支持时处理TIdSASLLogin),并将它们链接到AUTH LOGIN以获取TIdUserPassProviderUsername(在SASL身份验证期间不会使用PasswordTIdSMTP.Username属性。

现在,就是说,我使用TIdSMTP.Password测试了TIdSMTP,事实上,在建立SSL / TLS会话后,它确实报告了对smtp.live.com身份验证的支持,因此{ {1}}不适用于该服务器。使用LOGIN时,或ValidateAuthLoginCapabilityAUTH LOGIN一起使用时,会发送AuthType=satDefault命令。

但是,当使用我的真实 Hotmail密码时,服务器拒绝我使用TIdSASLLogin的登录尝试,这是因为我的帐户启用了两步验证。因此,为了使AuthType=satSASL能够正确登录,我必须使用网络浏览器进入我的Hotmail帐户并在安全设置中创建应用程序密码,然后配置{{1}使用那个密码而不是我的真正的密码。然后AUTH LOGIN成功。

如果您在Hotmail帐户中启用了两步验证,则必须执行相同的操作。

TIdSMTP

请注意,TIdSMTP支持的唯一其他身份验证方案是AUTH LOGIN * ,不需要创建应用密码。 Indy does not currently implementation XOAUTH2。但如果环顾四周,可能会有第三方实施。或者,您可以尝试自己实现自定义SMTP.AuthType := satDefault; SMTP.IOHandler := SSLHandler; SMTP.Host := 'smtp.live.com'; SMTP.Port := 587; SMTP.Username := 'real hotmail email here'; SMTP.Password := 'app password here'; // <-- SMTP.UseTLS := utUseExplicitTLS; 派生的组件。

* 仅供参考,Gmail还支持SMTP和IMAP smtp.live.com