在 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
属性 为 satDefault
,TIdSMTP.ValidateAuthLoginCapability
属性 为 True。这意味着 TIdSMTP.Username
和 TIdSMTP.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-SHA1
或 CRAM-MD5
。因此,您可以改为设置 AuthType=satSASL
,然后使用相关的 TIdSASL
派生组件填充 TIdSMTP.SASLMechanisms
集合(包括 TIdSASLLogin
以在支持时处理 AUTH LOGIN
),和 link 它们到 TIdUserPassProvider
以获得 Username
和 Password
(在 SASL 身份验证期间不使用 TIdSMTP.Username
和 TIdSMTP.Password
属性)。
现在,话虽这么说,我用 smtp.live.com
测试了 TIdSMTP
,事实上,在 SSL/TLS 会话后,它确实报告了对 LOGIN
身份验证的支持已建立,因此 ValidateAuthLoginCapability
不适用于该服务器。 AUTH LOGIN
命令在使用 AuthType=satDefault
时发送,或者在使用 TIdSASLLogin
和 AuthType=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。
我想发送一封电子邮件 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
属性 为 satDefault
,TIdSMTP.ValidateAuthLoginCapability
属性 为 True。这意味着 TIdSMTP.Username
和 TIdSMTP.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-SHA1
或 CRAM-MD5
。因此,您可以改为设置 AuthType=satSASL
,然后使用相关的 TIdSASL
派生组件填充 TIdSMTP.SASLMechanisms
集合(包括 TIdSASLLogin
以在支持时处理 AUTH LOGIN
),和 link 它们到 TIdUserPassProvider
以获得 Username
和 Password
(在 SASL 身份验证期间不使用 TIdSMTP.Username
和 TIdSMTP.Password
属性)。
现在,话虽这么说,我用 smtp.live.com
测试了 TIdSMTP
,事实上,在 SSL/TLS 会话后,它确实报告了对 LOGIN
身份验证的支持已建立,因此 ValidateAuthLoginCapability
不适用于该服务器。 AUTH LOGIN
命令在使用 AuthType=satDefault
时发送,或者在使用 TIdSASLLogin
和 AuthType=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。