【问题标题】:How to search for a specific e-mail message in IMAP mailbox?如何在 IMAP 邮箱中搜索特定的电子邮件?
【发布时间】:2013-01-29 06:05:20
【问题描述】:

如何根据邮件中包含的特定文本检索特定的电子邮件?例如 Gmail 搜索的工作原理。如果您搜索电子邮件中的特定文本,则 Gmail 将检索与该文本关联的消息。最好没有任何循环。

【问题讨论】:

    标签: delphi delphi-xe2 imap


    【解决方案1】:

    您正在寻找SearchMailBox 方法。这是一个简单的示例,期望您的 IMAP 客户端(在本例中为 TIdIMAP4 类型的 IMAPClient 变量)已连接到 Gmail 服务器。对于那些寻找如何做到这一点的人,请查看 this postput 将此代码放在 try..finally 块中,靠近 IMAPClient.ConnectIMAPClient.Disconnect

    var
      // in this example is not shown how to connect to Gmail IMAP server but
      // it's expected that the IMAPClient object is already connected there
      IMAPClient: TIdIMAP4;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      I: Integer;
      MsgObject: TIdMessage;
      SearchInfo: array of TIdIMAP4SearchRec;
    begin
      // if the mailbox selection succeed, then...
      if IMAPClient.SelectMailBox('INBOX') then
      begin
        // set length of the search criteria to 1
        SetLength(SearchInfo, 1);
        // the SearchKey set to skBody means to search only in message body texts
        // for more options and explanation, see comments at the TIdIMAP4SearchKey
        // enumeration in the IdIMAP4.pas unit
        SearchInfo[0].SearchKey := skBody;
        // term you want to search
        SearchInfo[0].Text := 'Search term';
    
        // if the search in the selected mailbox succeed, then...
        if IMAPClient.SearchMailBox(SearchInfo) then
        begin
          // iterate the search results
          for I := 0 to High(IMAPClient.MailBox.SearchResult) do
          begin
            // make an instance of the message object
            MsgObject := TIdMessage.Create(nil);
            try
              // try to retrieve currently iterated message from search results
              // and if this succeed you can work with the MsgObject
              if IMAPClient.Retrieve(IMAPClient.MailBox.SearchResult[I], 
                MsgObject) then
              begin
                // here you have retrieved message in the MsgObject variable, so
                // let's do what what you need with the >> MsgObject <<
              end;
            finally
              MsgObject.Free;
            end;
          end;
        end;
      end;
    end;
    

    这里是 UTF-8 字符集的 IMAP 搜索的快速实现。由于受保护的ParseSearchResult 方法,它使用插入类:

    type
      TBasicSearchKey = (bskBcc, bskBody, bskCc, bskFrom, bskHeader, bskKeyword,
        bskSubject, bskText, bskTo);
    const
      IMAPSearchKeys: array [TBasicSearchKey] of string = ('BCC', 'BODY', 'CC',
        'FROM', 'HEADER', 'KEYWORD', 'SUBJECT', 'TEXT', 'TO');
    type
      TIdIMAP4 = class(IdIMAP4.TIdIMAP4)
      public
        function SearchMailBoxUTF8(const ASearchText: string;
          ASearchKey: TBasicSearchKey): Boolean;
      end;
    
    implementation
    
    { TIdIMAP4 }
    
    function TIdIMAP4.SearchMailBoxUTF8(const ASearchText: string;
      ASearchKey: TBasicSearchKey): Boolean;
    var
      SearchText: RawByteString;
    begin
      Result := False;
      CheckConnectionState(csSelected);
    
      SearchText := UTF8Encode(ASearchText);
      SendCmd(Format('SEARCH CHARSET UTF-8 %s {%d}', [IMAPSearchKeys[ASearchKey],
        Length(SearchText)]), ['SEARCH']);
      if LastCmdResult.Code = IMAP_CONT then
        IOHandler.WriteLn(SearchText, TEncoding.UTF8);
    
      if GetInternalResponse(LastCmdCounter, ['SEARCH'], False) = IMAP_OK then
      begin
        ParseSearchResult(FMailBox, LastCmdResult.Text);
        Result := True;
      end;
    end;
    

    及用法:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      I: Integer;
      MsgObject: TIdMessage;
    begin
      if IMAPClient.SelectMailBox('INBOX') and
        IMAPClient.SearchMailBoxUTF8('Search term', bskText) then
      begin
        for I := 0 to High(IMAPClient.MailBox.SearchResult) do
        begin
          MsgObject := TIdMessage.Create(nil);
          try
            if IMAPClient.Retrieve(IMAPClient.MailBox.SearchResult[I],
              MsgObject) then
            begin
              // here you have retrieved message in the MsgObject variable, so
              // let's do what what you need with the >> MsgObject <<
            end;
          finally
            MsgObject.Free;
          end;
        end;
      end;
    end;
    

    【讨论】:

    • 这是返回 HTML 还是纯文本?因为如果您在纯文本的电子邮件中搜索内容,则可以正常工作。如果它们是 HTML 搜索将不起作用。
    • 这取决于SEARCH 命令的目标 IMAP 服务器实现,但不幸的是在这种情况下它不会搜索文本消息部分。值得一提。
    • 我认为有一种方法可以设置在 gmail 设置中返回纯 html 或文本。
    • 我不这么认为。当您调用SearchMailBox 时,您只需将命令发送到服务器,例如SEARCH BODY "Search term",它是由服务器决定的,它是如何接受的以及返回给您的。如果可以单独配置,我会感到惊讶。他们的搜索可能会有所不同,他们可以在眨眼间循环所有消息,因为他们在现场,所以可能不会使用SEARCH 命令。
    • 好吧,我一直在寻找更通用的解决方案。是否有其他 IMAP 服务器允许这样做? Hotmail/Yahoo 等。因为我可以采用其他服务。
    猜你喜欢
    • 2015-06-09
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-28
    • 1970-01-01
    • 2012-05-03
    • 2017-12-21
    相关资源
    最近更新 更多