Labels and messages
Gmail organizes mail with labels rather than a folder hierarchy — a
message can carry several labels at once (its Inbox membership, STARRED,
IMPORTANT, and any user-created labels), and TTMSFNCCloudGoogleGmail
reads both the account's labels and its messages. Every request is
asynchronous — a method returns immediately and the result arrives in a
matching On... event, with the retrieved data exposed through a collection
property on the component. This chapter covers listing labels, retrieving
messages with a Gmail search query, and knowing when a full page of messages
is actually ready to read.
Listing labels
GetLabels retrieves the account's labels into the read-only Labels
collection, raising OnGetLabels when they are available. Both system labels
(INBOX, STARRED, IMPORTANT, …) and user-created labels are returned,
distinguished by LabelType.
procedure TForm1.ListGmailLabels;
begin
TMSFNCCloudGoogleGmail1.OnGetLabels := GmailLabelsListed;
TMSFNCCloudGoogleGmail1.GetLabels;
end;
procedure TForm1.GmailLabelsListed(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
i: Integer;
begin
if not ARequestResult.Success then
Exit;
for i := 0 to TMSFNCCloudGoogleGmail1.Labels.Count - 1 do
Memo1.Lines.Add(TMSFNCCloudGoogleGmail1.Labels[i].Name
+ ' (' + TMSFNCCloudGoogleGmail1.Labels[i].LabelType + ')');
end;
Retrieving messages
GetMails retrieves messages carrying the given label(s) ('INBOX' by
default), with an optional Gmail search AQuery (the same syntax as the
Gmail search box, for example has:attachment from:someone@example.com) to
further filter the results. AMaxResults caps the page size, and
GetNextPage automatically continues fetching subsequent pages until every
matching message has been retrieved.
procedure TForm1.SearchUnreadWithAttachments;
begin
TMSFNCCloudGoogleGmail1.OnGetMailsComplete := GmailMessagesReady;
// AQuery uses Gmail's own search syntax.
TMSFNCCloudGoogleGmail1.GetMails('INBOX', 50, True, 'is:unread has:attachment');
end;
procedure TForm1.GmailMessagesReady(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
i: Integer;
m: TTMSFNCCloudGoogleGmailMessage;
begin
if not ARequestResult.Success then
Exit;
// Safe to read Mails here: every page and every message detail has loaded.
for i := 0 to TMSFNCCloudGoogleGmail1.Mails.Count - 1 do
begin
m := TMSFNCCloudGoogleGmail1.Mails[i];
Memo1.Lines.Add(m.Subject + ' - ' + m.From);
end;
end;
OnGetMails vs OnGetMailsComplete
GetMails does more work behind the scenes than a single list call: for
every message ID returned by the list, the component also fetches that
message's full details (subject, body, headers, labels). OnGetMails can
fire while those per-message detail requests are still in flight, so Mails
is not guaranteed to be fully populated yet. Wait for OnGetMailsComplete
— which only fires once every page and every message detail has finished
loading — before reading Mails for a complete result.
Combining a label listing with a filtered message page
Listing the labels first lets you resolve a label's ID before filtering messages by it — here the labels are listed, and the first user-created label found is used to retrieve its messages:
procedure TForm1.BrowseLabelsThenMessages;
begin
TMSFNCCloudGoogleGmail1.OnGetLabels := ListedThenGetMails;
TMSFNCCloudGoogleGmail1.OnGetMailsComplete := GmailLabelMessagesReady;
TMSFNCCloudGoogleGmail1.GetLabels;
end;
procedure TForm1.ListedThenGetMails(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
i: Integer;
begin
if not ARequestResult.Success then
Exit;
for i := 0 to TMSFNCCloudGoogleGmail1.Labels.Count - 1 do
begin
if TMSFNCCloudGoogleGmail1.Labels[i].LabelType = 'user' then
begin
TMSFNCCloudGoogleGmail1.GetMails(TMSFNCCloudGoogleGmail1.Labels[i].ID, 25, True);
Break;
end;
end;
end;
procedure TForm1.GmailLabelMessagesReady(Sender: TObject;
const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
i: Integer;
begin
if ARequestResult.Success then
for i := 0 to TMSFNCCloudGoogleGmail1.Mails.Count - 1 do
Memo1.Lines.Add(TMSFNCCloudGoogleGmail1.Mails[i].Subject);
end;
Common mistakes
- Reading
MailsfromOnGetMailsinstead ofOnGetMailsComplete. The collection can still be filling in per-message details at that point; see above. - Assuming
GetNextPage = Trueretrieves everything in one event. Pagination still happens behind the scenes across multiple requests; onlyOnGetMailsCompletesignals that all pages have arrived.
Related API
TTMSFNCCloudGoogleGmail—GetLabels,GetMails,Labels,Mails,OnGetLabels,OnGetMails,OnGetMailsCompleteTTMSFNCCloudGoogleGmailMessage—Subject,From,ToRecipients,Labels,HasAttachments