我对 Indy 很陌生,所以如果这里有一些明显的问题,我深表歉意。
我正在尝试从 Gmail 收件箱中检索电子邮件,然后将它们保存到一组
TIdMessage
对象中。
我找不到任何详细说明如何设置它的文档,也找不到工作示例(Indy 文档已损坏),而且我处理电子邮件的知识基本上为零。
procedure TfrmEmail.LoadInbox;
var
IMAP:TIdIMAP4;
iLength,i:integer;
SSL:TIdSSLIOHandlerSocketOpenSSL;
begin
SSL:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
//Set-Up SSL
with SSL.SSLOptions do
begin
Method:=sslvTLSv1;
Mode:=sslmClient;
VerifyMode:=[];
VerifyDepth:=0;
end;
IMAP:=TIdIMAP4.Create(Nil);
//IMAP settings
with IMAP do
begin
IOHandler:=SSL;
Host:='imap.gmail.com';
Port:=993;
Username:={[email protected]};
Password:={app password};
UseTLS:=utUseImplicitTLS;
Connect; //works up until here
SelectMailBox('INBOX');//error here
end;
iLength:=IMAP.RetrieveMailBoxSize;
ShowMessage(inttostr(iLength));
SetLength(ArrInboxMessages,iLength);
for i := 1 to iLength do
begin
IMAP.Retrieve(i,ArrInboxMessages[i]);
end;
IMAP.Disconnect;
IMAP.Free;
end;
我的代码在
Connect
部分之前一直有效,但是一旦我尝试选择收件箱,我就会收到异常:EIdConnectionStateError
。
我的连接状态未经身份验证,我认为这是因为我没有使用 SASL 身份验证。
另一个问题可能是我使用的是 TLSv1,但这适用于 SMTP,并且我无法在 Delphi 2010 上更新到最新版本。
如果有人能够识别问题并提供一个可行的示例/在哪里可以找到示例,那将非常有帮助。
使用应用程序密码并将
TIdIMAP4.AuthType
设置为 iatUserPass
(其默认设置)应该可以正常工作,您不需要使用 SASL+OAuth(尽管 GMail 更喜欢这样做)。
您显示的代码对我来说看起来不错。
TIdIMAP4.Connect()
有一个可选的 AAutoLogin
参数,默认为 True
,因此 TIdIMAP4.Login()
应该在 Connect()
退出之前被调用。如果 Login()
失败,您将收到不同的异常,并且您将无法首先到达 TIdIMAP4.SelectMailBox()
。
话虽如此,您收到的
EIdConnectionStateError
异常意味着当您调用 TIdIMAP4.ConnectionState
时,csAuthenticated
不是 csSelected
(或 SelectMailBox()
)。 ConnectionState
在csNonAuthenticated
和Connect()
的最开始设置为Login()
,然后如果身份验证成功,Login()
将其更新为csAuthenticated
。 因此,除非 Login()
被绕过,否则您的错误应该是不可能的,即如果 AAutoLogin=False
。
如果需要,您可以尝试在
Login()
之后和Connect()
之前显式调用SelectMailBox()
,例如:
Connect;
if ConnectionState <> csAuthenticated then
Login;
SelectMailBox('INBOX');
更新:
我没有注意到你使用的是非常旧版本的 Delphi。
我仔细检查了
TIdIMAP4
的源代码,了解 Delphi 2010 附带的 Indy 版本,我发现 Login()
当时实际上并没有在失败时引发异常。该问题在一年后得到解决(可能在 Delphi XE2 中发布)。
因此,在您的情况下,身份验证可能实际上失败,并且当
ConnectionState
/csNonAuthenticated
无一例外退出时,Connect()
被保留为 Login()
。这可以解释你的情况。
因此,您需要仔细检查您的凭据是否正确。您还可以在
TIdIMAP4.LastCmdResult.Code
/'OK'
退出后检查Connect()
是否为Login()
,例如:
Connect;
if LastCmdResult.Code <> 'OK' then
RaiseExceptionForLastCmdResult;
SelectMailBox('INBOX');
但是,我建议从其 GitHub 存储库升级到 Indy 的最新版本,以确保您拥有所有最新的修复程序,包括
Login()
在失败时引发异常的修复程序。即使您使用的是旧的 Delphi 版本,您也可以更新 Indy,因为 Indy 仍然支持 Delphi 2010。请参阅存储库 Wiki 中的更新 Indy 文档。