如何在Indy中从SendCmd获得可解析的响应?

时间:2015-09-19 18:49:24

标签: delphi indy indy10

如果我使用TIdImap4.SendCmd手动向Indy发送不支持的命令,我有点困惑如何检索完整响应以手动解析它。

我发送以下命令手动请求邮件的Gmail标签,因为这是not yet supported by Indy

  IMAP.SendCmd(ImapCmdNum(),'UID FETCH '+uid+' (X-GM-LABELS)',['OK','BAD','NO'], false);

调用此命令后,我检查了我的Indy Log文件,并且它已成功从服务器接收到相应的响应:

Sent 9/19/2015 11:10:40 AM: C5 UID FETCH 2385 (X-GM-LABELS)<EOL>
Recv 9/19/2015 11:10:40 AM: * 542 FETCH (X-GM-LABELS (testlabel) UID 2385)<EOL>C5 OK Success<EOL>

但是现在我似乎无法获得该回复的任何部分而不是&#39; OK&#39;来自Indy。我在调试器中尝试了以下操作,但没有一个具有原始响应或我可以手动解析的任何其他内容:

IMAP.LastCmdResult = ('OK', $2521E60, nil, $2521EC0)
IMAP.LastCmdResult.Text = ()
IMAP.LastCmdResult.Code = 'OK'
IMAP.LastCmdResult.NumericCode = 0
IMAP.LastCmdResult.FormattedReply = ()

来自SendCmd文档:

  

SendCmd是一个用于发送指定命令的重载函数   在AOut到对等连接。

     

SendCmd使用IOHandler将AOut中的命令写入对等体   连接。

     

AResponse表示该命令允许的响应。

     

SendCmd调用GetResponse 以确定来自对等方的响应   允许连接。如果不允许响应,则会出现异常   在GetResponse中处理期间引发。

     

当AResponse包含-1时,调用GetResponse为空   数组,表示该命令允许任何响应代码。   否则,AResponse中的值用于验证响应代码。

     

使用LastCmdResult访问的数字和文本部分   对命令的响应。

我对此的理解是我应该使用LastCmdResult来访问响应的各个部分&#34;但是没有一个具有原始响应或响应的任何部分,除了&#34; OK&# 34;,那么如何从SendCmd的响应中获取可解析的内容?

1 个答案:

答案 0 :(得分:1)

您要查找的文本实际上位于LastCmdResult.Text属性中。调试器没有向您显示,但这是标签数据的位置。

正如我2个月前在my other answer的评论中告诉你的那样,你链接到:

  

查看TIdIMAP4.UIDRetrieveFlags()的实施情况。它调用SendCmd()后跟ParseLastCmdResult()来解析返回的标志。您将不得不复制相同的逻辑,用fdGmailLabels替换当前正在使用fdFlags的地方(减去对正在解析标志字符串的ParseMessageFlagString()的调用TIdMessageFlagsSet)。

如果您查看TIdIMAP4.UIDRetrieveFlags()的实施情况,然后查看您的代码,那么您甚至无法正确地调用SendCmd()。您将错误的值传递给ATag参数(unless ImapCmdNum()只是调用TIdIMAP4.NewCmdCounter - TIdIMAP4需要生成命令计数器,以便它们可以将它们与回复相匹配),并且重要的是,您将错误的值传递给AExpectedResponses参数。

尝试这个(我测试了它并且它有效):

type
  TIdIMAP4Access = class(TIdIMAP4);
  TIdIMAPLineStructAccess = class(TIdIMAPLineStruct);

var
  uid: string;
  labels: string;
begin
  ...
  uid := ...;
  labels := '';
  IMAP.SendCmd('UID FETCH ' + uid + ' (X-GM-LABELS)', ['FETCH','UID']);
  if IMAP.LastCmdResult.Code = IMAP_OK then
  begin
    if IMAP.LastCmdResult.Text.Count > 0 then
    begin
      // The requested data is in IMAP.LastCmdResult.Text[0].

      // You can either parse it manually, or use the below
      // code to let TIdIMAP4 parse it for you...

      if TIdIMAP4Access(IMAP).ParseLastCmdResult(IMAP.LastCmdResult.Text[0], 'FETCH', ['X-GM-LABELS']) then begin
        labels := TIdIMAPLineStructAccess(TIdIMAP4Access(IMAP).FLineStruct).IMAPValue;
      end;
    end;
  end;
  ...
end;