How to get body texts of all e-mail messages from a certain IMAP mailbox?
Asked Answered
F

1

6

How to get body texts of all e-mail messages from a certain IMAP mailbox in Delphi ? For example, from the INBOX mailbox ?

Faun answered 28/11, 2012 at 14:19 Comment(5)
Do you want to have such retrieved messages to be marked as read ?Dishonorable
@Dishonorable Yea just to read whats is in the inbox so it don't really matter.Faun
@Dishonorable yea pure basic html so you can parse it later.Faun
Sorry, I've deleted my comment at the same time you've responded to it. For the others, I was asking if it's fine to deal with HTML body content.Dishonorable
@Dishonorable ye is no problem. Pure HTML is perfect :)Faun
D
13

There are many ways to retrieve all body texts of all messages from the selected mailbox. I've used the one, where you iterate the mailbox and Retrieve every single message from the mailbox one by one. This way allows you to modify the code, so that you'll be able to break the loop when you need or e.g. replace Retrieve by RetrievePeek which won't mark the message as read on server like the first mentioned does. When the message is retrieved from server, all its parts are iterated and when it's the text part, its body is appended to a local S variable. After the iteration the S variable is added to the output BodyTexts string list. So, as the result you'll get string list collection where each item consists from the concatenated message's text part bodies and where each item means one message.

uses
  IdIMAP4, IdSSLOpenSSL, IdText, IdMessage, IdExplicitTLSClientServerBase;

procedure GetGmailBodyTextParts(const UserName, Password: string;
  BodyTexts: TStrings);
var
  S: string;
  MsgIndex: Integer;
  MsgObject: TIdMessage;
  PartIndex: Integer;
  IMAPClient: TIdIMAP4;
  OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
  BodyTexts.Clear;
  IMAPClient := TIdIMAP4.Create(nil);
  try
    OpenSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    try
      OpenSSLHandler.SSLOptions.Method := sslvSSLv3;
      IMAPClient.IOHandler := OpenSSLHandler;
      IMAPClient.Host := 'imap.gmail.com';
      IMAPClient.Port := 993;
      IMAPClient.UseTLS := utUseImplicitTLS;
      IMAPClient.Username := UserName;
      IMAPClient.Password := Password;
      IMAPClient.Connect;
      try
        if IMAPClient.SelectMailBox('INBOX') then
        begin
          BodyTexts.BeginUpdate;
          try
            for MsgIndex := 1 to IMAPClient.MailBox.TotalMsgs do
            begin
              MsgObject := TIdMessage.Create(nil);
              try
                S := '';
                IMAPClient.Retrieve(MsgIndex, MsgObject);
                MsgObject.MessageParts.CountParts;
                if MsgObject.MessageParts.TextPartCount > 0 then
                begin
                  for PartIndex := 0 to MsgObject.MessageParts.Count - 1 do
                    if MsgObject.MessageParts[PartIndex] is TIdText then
                      S := S + TIdText(MsgObject.MessageParts[PartIndex]).Body.Text;
                  BodyTexts.Add(S);
                end
                else
                  BodyTexts.Add(MsgObject.Body.Text);
              finally
                MsgObject.Free;
              end;
            end;
          finally
            BodyTexts.EndUpdate;
          end;
        end;
      finally
        IMAPClient.Disconnect;
      end;
    finally
      OpenSSLHandler.Free;
    end;
  finally
    IMAPClient.Free;
  end;
end;

This code requires OpenSSL, so don't forget to put the libeay32.dll and ssleay32.dll libraries to a path visible to your project; you can download OpenSSL libraries for Indy in different versions and platforms from here.

Dishonorable answered 28/11, 2012 at 16:36 Comment(8)
Humm it won't retrieve emails bigger than 255 characters, hmmmFaun
Sorry, my fault. I'll have to update this code. It's not about character count, it's about plain text emails, they don't have stored body text in message part.Dishonorable
I've added the check for the message text part count. If it's 0 then the body is taken from the TIdMessage object. I hope it's enough, but I'd be calmer when Remy will say something about it.Dishonorable
is there a better way to retrieve emails? Based on something that is in the email without downloading them all..Faun
Yes, you can download just envelopes just like e-mail clients usually do. That gives you only the following information about the message: date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, and message ID. Then by the message ID you can download the whole message. You've just asked how to get body text of all messages and I'm afraid that for instance RetrieveText won't be enough since it won't retrieve text message parts, but only a plain message body.Dishonorable
well i don't want to loop through all them and then regex_match them all to find a specific email that has a text in it.Faun
I see, but in that case my answer is not valid anymore since you need to use SearchMailBox method for this. If you'd said that on the beginning we could save a lot of time to each other. Your questions can be useful to the others, but they won't when you change them so radically. Please rollback the changes on your update and ask this as a separate questiton again. And, at this time please try to focus on what you really need. Thanks!Dishonorable
Rolled back :) will post a new question.Faun

© 2022 - 2024 — McMap. All rights reserved.