Search code examples
c++builderindy10

Read email body from a certain IMAP mailbox


I'm trying to find a way to read only text from an email. Unfortunately, in Memo1 there is still information about attachments as well as all information about the structure of the e-mail.

if ( IdIMAP1->UIDRetrieve( UID, IdMessage1 ) )
{
    IdMessage1->MessageParts->CountParts();
    if( IdMessage1->MessageParts->TextPartCount )
    {
        String b;

        IdIMAP1->UIDRetrieveText(UID, b);
        Memo1->Lines->Add( UTF8Decode(b) );
    }
}

I tried to use the TIdText function but the result Str is empty.

TStrings* Str = new TStringList;
TIdText( IdMessage1->MessageParts, Str );

ContentType of mesage is multipart but parts of mesage contains also text/plain type.

IdIMAP1->UIDRetrieveHeader(UID, IdMessage1);
IdMessage1->ContentType;

I tried to isolate the text part of the email but that didn't help either.

TIdMessagePart *Part;

for( int j = 0; j < IdMessage1->MessageParts->Count; ++j )
{
   Part = IdMessage1->MessageParts->Items[j];
   
  if( IsHeaderMediaType(Part->ContentType, "text/plain")
  {
    String b;
    IdIMAP1->UIDRetrieveText(UID, b);
  }
}

Do you have any idea?

Is this ok using stucture?

TIdMessagePart *Part;
IdIMAP1->UIDRetrieveHeader(UID, IdMessage1);
IdIMAP1->UIDRetrieveStructure( UID, IdMessage1 );

for( int j = 0; j < IdMessage1->MessageParts->Count; ++j )
{
   Part = IdMessage1->MessageParts->Items[j];
    
   if( IsHeaderMediaType(Part->ContentType, "text/plain")
   {
     String b;
     IdIMAP1->UIDRetrieveText(UID, b);
   }
   else { }
}



Solution

  • The statement TIdText( IdMessage1->MessageParts, Str ); does not do what you think. It adds a new TIdText object to the MessageParts, initializing the object's Body text with the specified TStrings text. Which is not what you want in this situation. Also, because Delphi-style objects (derived from TObject) must be created on the heap via new, so this statement should not even compile, producing an E2459 error.

    Since you are downloading the email's full content via UIDRetrieve(), there is no reason to download individual text pieces via UIDRetrieveText() afterwards. You can just scan the TIdMessage contents you already have for the text portion you want. In your 2nd example, replace this:

    String b;
    IdIMAP1->UIDRetrieveText(UID, b);
    

    with this:

    String b = static_cast<TIdText*>(Part)->Body->Text;
    

    Otherwise, you should take a different approach. IMAP is a very complex and flexible protocol. One of its features is it allows you to download an email's structure first (via UIDRetrieveStructure()), analyze those headers as needed to discover the PartNumber of the specific part(s) you want, and then you can download only those parts by themselves (via UIDRetrievePart()).