Jump to content
Fred (The Silva)

Readin Email with IMAP component

Recommended Posts

Hi.

 

How can I retrieve INBOX email messages in Indy 10.6.2, using "TIdIMAP4SearchRec" for *only* (filtering):

 

> "UnSeen" messages

> "Recent" messages

> Messages that have the word 'Sales' on Subject

 

Thanks,

Share this post


Link to post

Call the TIdIMAP4.(UID)SearchMailBox() method, providing it with an array of desired filter criteria. It will populate the TIdIMAP4.MailBox.SearchResult list with numbers/UIDs of matching emails, which you can then download with any of the various TIdIMAP4.(UID)Retrieve...() methods.

Share this post


Link to post

the issue is:

 

having

var
  LEMailSearchInfo        : array of TIdIMAP4SearchRec;
 

if I do:

      SetLength(LEMailSearchInfo, 1);
      LEMailSearchInfo[0].SearchKey := skUnseen;
 

it find a new (unseen) messages

 

If I do:

      SetLength(LEMailSearchInfo, 2);
      LEMailSearchInfo[0].SearchKey := skUnseen;
      LEMailSearchInfo[1].SearchKey := skRecent;

 

it didn't find the messages

 

Where can I get a tutorial on how to use and combine all TIdIMAP4SearchKey enum options?

Share this post


Link to post
Posted (edited)
2 hours ago, Fred (The Silva) said:

If I do:

      SetLength(LEMailSearchInfo, 2);
      LEMailSearchInfo[0].SearchKey := skUnseen;
      LEMailSearchInfo[1].SearchKey := skRecent;

 

it didn't find the messages

That will search for messages that are flagged as both UNSEEN AND RECENT.  If you want to search for UNSEEN OR RECENT instead, you will have to add a 3rd array entry for the skOr search key:

OR <search-key1> <search-key2>

For example:

SetLength(LEMailSearchInfo, 3);
LEMailSearchInfo[0].SearchKey := skOr;
LEMailSearchInfo[1].SearchKey := skUnseen;
LEMailSearchInfo[2].SearchKey := skRecent;

If you want to add a 3rd OR filter, you will need a 2nd skOk entry, eg:

SetLength(LEMailSearchInfo, 5);

LEMailSearchInfo[0].SearchKey := skOr;

LEMailSearchInfo[1].SearchKey := skOr;
LEMailSearchInfo[2].SearchKey := skUnseen;
LEMailSearchInfo[3].SearchKey := skRecent;

LEMailSearchInfo[4].SearchKey := skSubject;
LEMailSearchInfo[4].Text := 'Sales';
// or:
LEMailSearchInfo[4].SearchKey := skHeader;
LEMailSearchInfo[4].FieldName := 'Subject';
LEMailSearchInfo[4].Text := 'Sales';
Quote

Where can I get a tutorial on how to use and combine all TIdIMAP4SearchKey enum options?

There isn't one, unfortunately.  The (UID)SearchMailBox() methods are just a thin wrapper for the IMAP SEARCH command, so you'll have to read RFC 3501 Section 6.4.4 for how search semantics work.  Also, https://stackoverflow.com/questions/12809709/ has some good information about using multiple ORs with IMAP search.

Edited by Remy Lebeau

Share this post


Link to post

@Remy Lebeau, to not to open a new thread, because my question is related:

 

When I want to get emails when a specific text exist in the body, and another text does not exist, can I do it like this?

 

SetLength(sr,3);

sr[0].key:=skNot;

sr[1].key:=skBody;

sr[1].text:='This should not be in the body';

sr[2].key:=skBody;

sr[2].text:='This must be in th ebody';

 

Share this post


Link to post
4 hours ago, softtouch said:

When I want to get emails when a specific text exist in the body, and another text does not exist, can I do it like this?

Did you try it and see what happens?  (BTW, you have a typo in your search text, maybe that is contributing to you not being able to find emails?)

 

Offhand, what you show looks OK to me, as it would create this SEARCH command:

SEARCH NOT BODY "This should not be in the body" BODY "This must be in th ebody"

Which is logically treated like this:

SEARCH (NOT BODY "This should not be in the body") AND (BODY "This must be in th ebody")

But, if that doesn't work for you, then try reversing the order of the search keys:

SetLength(sr,3);
sr[0].key:=skBody;
sr[0].text:='This must be in th ebody';
sr[1].key:=skNot;
sr[2].key:=skBody;
sr[2].text:='This should not be in the body';

Which creates the command:

SEARCH BODY "This must be in th ebody" NOT BODY "This should not be in the body"

Which is treated as:

SEARCH (BODY "This must be in th ebody") AND (NOT BODY "This should not be in the body")

If it still doesn't work, then which email provider are you connected to, exactly?  Outlook 365, for instance, seems to be troublesome in regards to BODY searches (or at least, it was a couple of years ago):

 

https://answers.microsoft.com/en-us/outlook_com/forum/all/office365-imap-does-not-return-the-email-when-body/0a98b753-bb0d-4fa3-9488-773b98d8acc4

 

https://stackoverflow.com/questions/66034478/outlook-imap-search-not-returning-correct-value-with-body-search-criteria

 

Share this post


Link to post
17 hours ago, Remy Lebeau said:

Did you try it and see what happens?  (BTW, you have a typo in your search text, maybe that is contributing to you not being able to find emails?)

 

Offhand, what you show looks OK to me, as it would create this SEARCH command:


SEARCH NOT BODY "This should not be in the body" BODY "This must be in th ebody"

Which is logically treated like this:


SEARCH (NOT BODY "This should not be in the body") AND (BODY "This must be in th ebody")

But, if that doesn't work for you, then try reversing the order of the search keys:


SetLength(sr,3);
sr[0].key:=skBody;
sr[0].text:='This must be in th ebody';
sr[1].key:=skNot;
sr[2].key:=skBody;
sr[2].text:='This should not be in the body';

Which creates the command:


SEARCH BODY "This must be in th ebody" NOT BODY "This should not be in the body"

Which is treated as:


SEARCH (BODY "This must be in th ebody") AND (NOT BODY "This should not be in the body")

If it still doesn't work, then which email provider are you connected to, exactly?  Outlook 365, for instance, seems to be troublesome in regards to BODY searches (or at least, it was a couple of years ago):

 

https://answers.microsoft.com/en-us/outlook_com/forum/all/office365-imap-does-not-return-the-email-when-body/0a98b753-bb0d-4fa3-9488-773b98d8acc4

 

https://stackoverflow.com/questions/66034478/outlook-imap-search-not-returning-correct-value-with-body-search-criteria

 

I tried it and it seems to work. I assume if I have multiple "NOT" criteria, I need to do it like this?

 

sr[0].key:=skNot;

sr[1].key:='skBody;

sr[1].text:='This should not be in the body';

sr[2].key:='skBody;

sr[2].text:='This should also not be in the body';

 

So when it see the skNot, it will use only the next criteria for the skNot or until it get another sk??? criteria?

Share this post


Link to post
Posted (edited)
18 minutes ago, softtouch said:

I tried it and it seems to work.

I covered that in my earlier reply. That example is performing:

"SEARCH NOT BODY <body1> BODY <body2>"

which AFAIK is treated as:

"(NOT BODY <body1>) AND (BODY <body2>)"

18 minutes ago, softtouch said:

I assume if I have multiple "NOT" criteria, I need to do it like this?

NOT takes only 1 condition as input.  If you want multiple NOT conditions, you need multiple NOTs in the array, 1 for each condition, ie:

"SEARCH NOT <criteria1> NOT <criteria2>"

which is treated as:

"(NOT <criteria1>) AND (NOT <criteria2>)"

or:

"SEARCH NOT OR <critera1> <criteria2>"

which is treated as:

"NOT (<criteria1> OR <criteria2>)"

Quote

So when it see the skNot, it will use only the next criteria for the skNot or until it get another sk??? criteria?

Only 1 criteria per NOT.  Please read RFC 3501 Section 6.4.4

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×