if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TIdIMAP4SearchRec sr[1];
sr[0].SearchKey = skAll;
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
Error:
First chance exception at $757BF192. Exception class EIdReadLnMaxLineLengthExceeded with message 'Max line length exceeded.'.
It tries to read messages from the SENT folder and the program throws an error. There is no error when receiving from another SENT subfolder.
It seems to me that the problem lies in specifying SearchKey
when the value is set to skAll
, but no other setting reads the email despite the lack of an error. What does this error mean and how can I fix it?
By the way, I have a question about the SearchKey
settings. Is it possible to give a specific date here that would filter emails only from today, for example?
Error:
First chance exception at $757BF192. Exception class EIdReadLnMaxLineLengthExceeded with message 'Max line length exceeded.'.
... What does this error mean and how can I fix it?
It means TIdIMAP4
called the IOHandler.ReadLn()
method and received more than 16K worth of data that had no line breaks in it. The default value of the IOHandler.MaxLineLength
property is 16384
, and the default value of the IOHandler.MaxLineAction
is maException
.
To workaround the error, you could try increasing the value of the MaxLineLength
(say, to MaxInt
). However, a proper fix would be to prevent such a large amount of undelimited data to be received in the first place.
The response of UIDSearchMailBox()
is a single line containing a list of email sequence numbers delimited by spaces, so you could be getting the EIdReadLnMaxLineLengthExceeded
error here if the search is producing a LOT of sequence numbers (say, thousands of them, which makes sense when searching for just skAll
on a large mailbox).
You really should not be searching for just skAll
by itself to begin with. If you want to access all emails in the mailbox, just iterate the mailbox instead. After SelectMailBox()
returns success, TIdIMAP4.MailBox.TotalMsgs
will contain the number of emails currently in the mailbox. You can then run a loop retrieving individual emails as needed using sequence numbers in the range of 1..TotalMsgs
, inclusive.
Otherwise, filter your search criteria better to produce fewer results.
By the way, I have a question about the
SearchKey
settings. Is it possible to give a specific date here that would filter emails only from today, for example?
Yes, of course. Look at the TIdIMAP4SearchKey
enum, it lists all of the different keys you can search on, for instance:
skOn, //Messages whose internal date is within the specified date.
skSentOn, //Messages whose [RFC-822] Date: header is within the specified date.
skSentSince, //Messages whose [RFC-822] Date: header is within or later than the specified date.
skSince, //Messages whose internal date is within or later than the specified date.
In this case, either of those should work, depending on whether you want to search the email's internal server timestamps or their Date
headers, eg:
if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TIdIMAP4SearchRec sr[1];
sr[0].SearchKey = skSince;
sr[0].Date = Sysutils::Date(); // or Dateutils::Today()
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
UPDATE
this example refer to expresion 'later than the specified date' but I can see that it is possible to use 'within'. How to set range of data? Is it possible in
SearchKey
settings?
There is no 'within' search key in IMAP. If you are referring to RFC 5032: WITHIN Search Extension to the IMAP Protocol (the OLDER
and YOUNGER
search keys), then TIdIMAP4
does not implement this extension at this time. I have opened a ticket to add it in a future release:
#420: Update TIdIMAP4 to support RFC 5032: "WITHIN Search Extension to the IMAP Protocol"
In the meantime, you can combine multiple search keys and they will be logically AND
'ed together, eg:
if ( IdIMAP1->SelectMailBox( "SENT" ) )
{
TDateTime dtNow = Sysutils::Now();
TIdIMAP4SearchRec sr[2];
sr[0].SearchKey = skSince;
sr[0].Date = Dateutils::StartOfTheDay(Dateutils::IncDay(dtNow, -6));
sr[1].SearchKey = skBefore;
sr[1].Date = dtNow;
IdIMAP1->UIDSearchMailBox( EXISTINGARRAY(sr) );
int ile = IdIMAP1->MailBox->SearchResult.Length;
}
I suggest you read RFC 3501 Section 6.4.4 for how the SEARCH
command works and what the standard search keys are.