代码之家  ›  专栏  ›  技术社区  ›  user9210291

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

  •  0
  • user9210291  · 技术社区  · 6 年前

    我想发一封电子邮件 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 回复  |  直到 6 年前
        1
  •  4
  •   Remy Lebeau    6 年前

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

    在我详细介绍您的问题之前,让我给您一些信息,以便您了解如何 TIdSMTP 身份验证通常有效。

    默认情况下 TIdSMTP.AuthType 属性为 satDefault ,以及 TIdSMTP.ValidateAuthLoginCapability 属性为True。这意味着 TIdSMTP.Username TIdSMTP.Password 属性使用不安全的 AUTH LOGIN 命令(如果没有已建立的SSL/TLS会话,大多数服务器将不接受该命令),但仅当服务器 EHLO 答复表明: LOGIN 是一种可接受的身份验证(许多服务器不报告,即使它们确实接受)。

    因此,有可能 TIdSMTP.Authenticate() (您不需要手动调用, TIdSMTP.Send() 在以下情况下,甚至可能不会尝试向服务器进行身份验证 AuthType=satDefault ,然后调用 TIDMSMTP。发送() 可能会因身份验证错误而失败(您可以通过分配一个Indy TIdLog... 组件到 TIdSMTP.Intercept 属性,然后查看实际的SMTP命令 TIDMSMTP 发送)。

    所以,尝试设置 TIDMSMTP。ValidateAuthLogincability验证逻辑性 至False so TIDMSMTP。验证() 将始终发送 身份验证登录 什么时候 AuthType=satDefault ,无论服务器是否报告它是可接受的。如果服务器不接受它,至少会在该阶段而不是在 Send() 阶段

    然而,现在大多数SMTP服务器接受/需要比 登录名 例如 CRAM-SHA1 CRAM-MD5 . 所以,你可以设置 AuthType=satSASL 而是,然后填充 TIdSMTP.SASLMechanisms 与相关 TIdSASL -衍生组件(包括 TIdSASLLogin 处理 身份验证登录 支持时),并将它们链接到 TIdUserPassProvider 获取 Username Password (the TIDMSMTP。用户名 TIDMSMTP。暗语 属性在SASL身份验证期间不使用)。

    话虽如此,我测试过 TIDMSMTP 具有 smtp.live.com ,它确实报告了对 登录名 在建立SSL/TLS会话后进行身份验证,因此 ValidateAuthLoginCapability 不适用于该服务器。这个 身份验证登录 使用时发送命令 AuthType=satDefault ,或使用时 蒂德萨斯洛金 具有 AuthType=satSASL .

    但是,服务器拒绝我的登录尝试 身份验证登录 使用my时 真实的 Hotmail密码,这是因为我的帐户启用了两步验证。所以,为了 TIDMSMTP 要正确登录,我必须使用web浏览器进入我的Hotmail帐户并创建 应用程序密码 在安全设置中,然后配置 TIDMSMTP 使用 那个 密码而不是我的 真实的 暗语然后 身份验证登录 已成功。

    如果在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。居住通用域名格式 支架为 XOAUTH2 * ,不需要创建应用程序密码。 Indy does not currently implementation XOAUTH2 . 但如果您四处看看,可能会有第三方实现。或者,您可以尝试实现自定义 TIdSASL公司 -您自己的派生组件。

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