我想发送电子邮件 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');
版:
错误是:
身份验证失败
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;
答案 0 :(得分:4)
从错误消息中可以清楚地看出,服务器在发送电子邮件之前拒绝了您的身份验证尝试。
在我详细介绍您的问题之前,让我向您提供一些信息,以便了解TIdSMTP
身份验证的一般情况。
默认情况下,TIdSMTP.AuthType
属性为satDefault
,TIdSMTP.ValidateAuthLoginCapability
属性为True。这意味着TIdSMTP.Username
和TIdSMTP.Password
属性是使用不安全的AUTH LOGIN
命令发送的(大多数服务器在没有建立SSL / TLS会话的情况下都不会接受),但仅限于服务器的{{1}回复表明EHLO
是可接受的身份验证(许多服务器都不会报告,即使他们确实接受了它)。
因此,LOGIN
(您不需要手动调用,TIdSMTP.Authenticate()
为您调用它)可能甚至无法在TIdSMTP.Send()
时尝试向服务器进行身份验证,然后对AuthType=satDefault
的后续调用可能会因身份验证错误而失败(您可以通过将Indy的TIdSMTP.Send()
组件之一分配给TIdLog...
属性来验证这一点,然后查看实际的SMTP命令TIdSMTP.Intercept
发送)。
因此,请尝试将TIdSMTP
设置为False,以便TIdSMTP.ValidateAuthLoginCapability
在TIdSMTP.Authenticate()
时始终发送AUTH LOGIN
,无论服务器是否报告可接受。如果服务器不接受它,那么至少它将在该阶段而不是AuthType=satDefault
阶段验证失败。
但是,现在大多数SMTP服务器都接受/需要比Send()
更强的身份验证方案,例如LOGIN
或CRAM-SHA1
。因此,您可以设置CRAM-MD5
,然后使用相关的AuthType=satSASL
派生组件填充TIdSMTP.SASLMechanisms
集合(包括TIdSASL
以便在支持时处理TIdSASLLogin
),并将它们链接到AUTH LOGIN
以获取TIdUserPassProvider
和Username
(在SASL身份验证期间不会使用Password
和TIdSMTP.Username
属性。
现在,就是说,我使用TIdSMTP.Password
测试了TIdSMTP
,事实上,在建立SSL / TLS会话后,它确实报告了对smtp.live.com
身份验证的支持,因此{ {1}}不适用于该服务器。使用LOGIN
时,或ValidateAuthLoginCapability
与AUTH 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
。