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

IdSMTP fail to send email when executed inside a vps computer

我想发送一封电子邮件 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');

版本:

错误是:

Authentication unsuccessful

    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;

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

在详细说明您的问题之前,让我给您一些信息,以便您了解 TIdSMTP 身份验证的一般工作原理。

默认情况下,TIdSMTP.AuthType 属性 为 satDefaultTIdSMTP.ValidateAuthLoginCapability 属性 为 True。这意味着 TIdSMTP.UsernameTIdSMTP.Password 属性是使用不安全的 AUTH LOGIN 命令发送的(如果没有已建立的 SSL/TLS 会话,大多数服务器将不会接受),但前提是服务器的 EHLO 回复表示 LOGIN 是可接受的身份验证(许多服务器不报告,即使他们接受它)。

因此,当 AuthType=satDefault,然后对 TIdSMTP.Send() 的后续调用可能会因身份验证错误而失败(您可以通过将 Indy 的 TIdLog... 组件之一分配给 TIdSMTP.Intercept 属性 来验证这一点,然后查看TIdSMTP 发送的实际 SMTP 命令)。

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

然而,如今大多数 SMTP 服务器 accept/require 比 LOGIN 更强大的身份验证方案,例如 CRAM-SHA1CRAM-MD5。因此,您可以改为设置 AuthType=satSASL,然后使用相关的 TIdSASL 派生组件填充 TIdSMTP.SASLMechanisms 集合(包括 TIdSASLLogin 以在支持时处理 AUTH LOGIN),和 link 它们到 TIdUserPassProvider 以获得 UsernamePassword (在 SASL 身份验证期间不使用 TIdSMTP.UsernameTIdSMTP.Password 属性)。

现在,话虽这么说,我用 smtp.live.com 测试了 TIdSMTP,事实上,在 SSL/TLS 会话后,它确实报告了对 LOGIN 身份验证的支持已建立,因此 ValidateAuthLoginCapability 不适用于该服务器。 AUTH LOGIN 命令在使用 AuthType=satDefault 时发送,或者在使用 TIdSASLLoginAuthType=satSASL 时发送。

但是,当我使用 真实 Hotmail 密码时,服务器拒绝了我使用 AUTH LOGIN 的登录尝试,这是因为我的帐户启用了两步验证。因此,为了 TIdSMTP 正确登录,我必须使用网络浏览器进入我的 Hotmail 帐户并在安全设置中创建一个 应用程序密码 ,然后配置 TIdSMTP 使用 that 密码代替我的 real 密码。那么AUTH LOGIN就成功了

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

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;

请注意,smtp.live.com 唯一支持的其他身份验证方案是 XOAUTH2*,它不需要创建应用程序密码。 Indy does not currently implementation XOAUTH2。但是如果你环顾四周,可能会有一个 3rd 方实现。或者,您可以尝试自己为它实现自定义 TIdSASL 派生组件。

* 仅供参考,Gmail 还支持 XOAUTH2 SMTP 和 IMAP。