DataFlex
DataFlex
Outlook -- Search Multiple Folders
See more Outlook Examples
I don't yet see how it's possible to do a recursive search of Outlook folders using the Microsoft Graph API. My best guess is to somehow use OData v4.0's $expand query option, but the hierarchical structure of the "mailFolder" and "messages" Microsoft Graph resources don't quite fit. Suggestions are welcome and can be sent to support@chilkatsoft.com.This example will iterate over a list of folder previously obtained by a recursive traversal of the Outlook mail folders. (See the link in the example code below.)
A separate search is performed on each desired folder, and the results are combined into a single result set.
Note: This example requires Chilkat v9.5.0.68 or greater.
This example applies to: Exchange Online | Office 365 | Hotmail.com | Live.com | MSN.com | Outlook.com | Passport.com
Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
Handle hoHttp
Handle hoXmlMap
Handle hoJson
Handle hoJsonCombined
Variant vSbResponse
Handle hoSbResponse
Handle hoSbPath
Integer iNumFolders
Integer i
Integer j
Integer k
Integer iNumMessages
String sTemp1
Integer iTemp1
Boolean bTemp1
Move False To iSuccess
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
Get Create (RefClass(cComChilkatHttp)) To hoHttp
If (Not(IsComObjectCreated(hoHttp))) Begin
Send CreateComObject of hoHttp
End
// Use your previously obtained access token here:
// See the following examples for getting an access token:
// Get Microsoft Graph OAuth2 Access Token (Azure AD v2.0 Endpoint).
// Get Microsoft Graph OAuth2 Access Token (Azure AD Endpoint).
// Refresh Access Token (Azure AD v2.0 Endpoint).
// Refresh Access Token (Azure AD Endpoint).
Set ComAuthToken Of hoHttp To "MICROSOFT_GRAPH_ACCESS_TOKEN"
// This example will iterate over the folders previously discovered by recursively traversing the Outlook folders
// as shown in this example: Outlook Recursive Folder Traversal)
// The XML map produced by the recursive traversal looks like this:
// <?xml version="1.0" encoding="utf-8"?>
// <hashtable>
// <e><k>/Sent Items</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEJAAAA</v></e>
// <e><k>/Inbox</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA</v></e>
// <e><k>/Junk Email</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEiAAAA</v></e>
// <e><k>/Inbox/xyz</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwEAAAA=</v></e>
// <e><k>/Inbox/abc/subFolderA/a</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwIAAAA=</v></e>
// <e><k>/Inbox/abc</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huv8AAAA=</v></e>
// <e><k>/Outbox</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgELAAAA</v></e>
// <e><k>/Inbox/abc/subFolderA</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwAAAQ==</v></e>
// <e><k>/Inbox/abc/subFolderB</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwMAAAA=</v></e>
// <e><k>/Archive</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAG8XunwAAAA=</v></e>
// <e><k>/Deleted Items</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEKAAAA</v></e>
// <e><k>/Drafts</k><v>AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEPAAAA</v></e>
// </hashtable>
// We'll iterate over the folders, and search all folders beginning with "/Inbox" (effectively, we're recursively searching
// everything under Inbox)
Get Create (RefClass(cComChilkatXml)) To hoXmlMap
If (Not(IsComObjectCreated(hoXmlMap))) Begin
Send CreateComObject of hoXmlMap
End
Get ComLoadXmlFile Of hoXmlMap "qa_data/outlook/folderMap.xml" To iSuccess
If (iSuccess <> True) Begin
Showln "Failed to load XML folder map."
Procedure_Return
End
// We're going to return just the message id, subject, and FROM name/address.
Get ComSetUrlVar Of hoHttp "select" "id,subject,from" To iSuccess
// Our search will be for emails with the word "sample" in the subject.
Get ComSetUrlVar Of hoHttp "filter" "contains(subject,'sample')" To iSuccess
Get Create (RefClass(cComChilkatJsonObject)) To hoJson
If (Not(IsComObjectCreated(hoJson))) Begin
Send CreateComObject of hoJson
End
Set ComEmitCompact Of hoJson To False
Get Create (RefClass(cComChilkatJsonObject)) To hoJsonCombined
If (Not(IsComObjectCreated(hoJsonCombined))) Begin
Send CreateComObject of hoJsonCombined
End
Set ComEmitCompact Of hoJsonCombined To False
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbResponse
If (Not(IsComObjectCreated(hoSbResponse))) Begin
Send CreateComObject of hoSbResponse
End
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbPath
If (Not(IsComObjectCreated(hoSbPath))) Begin
Send CreateComObject of hoSbPath
End
Get ComNumChildren Of hoXmlMap To iNumFolders
Move 0 To i
Move 0 To j
Move 0 To k
While (i < iNumFolders)
Set ComI Of hoXmlMap To i
Get ComGetChildContent Of hoXmlMap "e[i]|k" To sTemp1
Get ComSetString Of hoSbPath sTemp1 To iSuccess
Get ComStartsWith Of hoSbPath "/Inbox" True To bTemp1
If (bTemp1 = True) Begin
Showln "------------------------------------------------------------------"
Get ComGetAsString Of hoSbPath To sTemp1
Showln "Searching " sTemp1
// Search this mail folder..
Get ComGetChildContent Of hoXmlMap "e[i]|v" To sTemp1
Get ComSetUrlVar Of hoHttp "folder_id" sTemp1 To iSuccess
Send ComClear To hoSbResponse
Get pvComObject of hoSbResponse to vSbResponse
Get ComQuickGetSb Of hoHttp "https://graph.microsoft.com/v1.0/me/mailFolders/{$folder_id}/messages?$filter={$filter}&$select={$select}" vSbResponse To iSuccess
Get ComLastStatus Of hoHttp To iTemp1
If ((iSuccess <> True) And (iTemp1 = 0)) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
Get pvComObject of hoSbResponse to vSbResponse
Get ComLoadSb Of hoJson vSbResponse To iSuccess
Get ComLastStatus Of hoHttp To iTemp1
If (iTemp1 <> 200) Begin
Get ComLastStatus Of hoHttp To iTemp1
Showln "HTTP response status = " iTemp1
Get ComEmit Of hoJson To sTemp1
Showln sTemp1
Showln "Failed."
Procedure_Return
End
Get ComEmit Of hoJson To sTemp1
Showln sTemp1
// Each mail folder search will return JSON with a value array, which is non-empty if any matching messages were found:
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA')/messages(id,subject,from)",
// "value": [
// Individual messages, if any, are listed here.
// ]
// }
Get ComSizeOfArray Of hoJson "value" To iNumMessages
Move 0 To j
While (j < iNumMessages)
Set ComJ Of hoJson To j
// Add this message to the final result set.
Set ComK Of hoJsonCombined To k
Get ComGetAsString Of hoSbPath To sTemp1
Get ComUpdateString Of hoJsonCombined "value[k].folderPath" sTemp1 To iSuccess
Get ComStringOf Of hoJson "value[j].id" To sTemp1
Get ComUpdateString Of hoJsonCombined "value[k].id" sTemp1 To iSuccess
Get ComStringOf Of hoJson "value[j].subject" To sTemp1
Get ComUpdateString Of hoJsonCombined "value[k].subject" sTemp1 To iSuccess
Get ComStringOf Of hoJson "value[j].from.emailAddress.name" To sTemp1
Get ComUpdateString Of hoJsonCombined "value[k].from.emailAddress.name" sTemp1 To iSuccess
Get ComStringOf Of hoJson "value[j].from.emailAddress.address" To sTemp1
Get ComUpdateString Of hoJsonCombined "value[k].from.emailAddress.address" sTemp1 To iSuccess
Move (k + 1) To k
Move (j + 1) To j
Loop
End
Move (i + 1) To i
Loop
// Show the final combined JSON search result.
Showln "------------------------------------------------------------------"
Showln "Combined Search Results:"
Get ComEmit Of hoJsonCombined To sTemp1
Showln sTemp1
// Sample output for the above program:
// ------------------------------------------------------------------
// Searching /Inbox
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA')/messages(id,subject,from)",
// "value": [
// {
// "@odata.etag": "W/\"CQAAABYAAADn68XtMop0TpsYJGpfKXY9AADOpwfr\"",
// "id": "AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgBGAAADsVyfxjDU406Ic4X7ill8xAcA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA5_vF7TKKdE6bGCRqXyl2PQAAAM6Jj10AAAA=",
// "subject": "A sample email with Amazon in the body",
// "from": {
// "emailAddress": {
// "name": "Chilkat Software",
// "address": "support@chilkatsoft.com"
// }
// }
// }
// ]
// }
//
// ------------------------------------------------------------------
// Searching /Inbox/xyz
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwEAAAA%3D')/messages(id,subject,from)",
// "value": [
// ]
// }
//
// ------------------------------------------------------------------
// Searching /Inbox/abc/subFolderA/a
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwIAAAA%3D')/messages(id,subject,from)",
// "value": [
// {
// "@odata.etag": "W/\"CQAAABYAAADn68XtMop0TpsYJGpfKXY9AADOpzfb\"",
// "id": "AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgBGAAADsVyfxjDU406Ic4X7ill8xAcA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwIAAADn68XtMop0TpsYJGpfKXY9AAAAzombFQAAAA==",
// "subject": "Sample email from admin@chilkat.io",
// "from": {
// "emailAddress": {
// "name": "Chilkat Software",
// "address": "admin@chilkat.io"
// }
// }
// }
// ]
// }
//
// ------------------------------------------------------------------
// Searching /Inbox/abc
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huv8AAAA%3D')/messages(id,subject,from)",
// "value": [
// ]
// }
//
// ------------------------------------------------------------------
// Searching /Inbox/abc/subFolderA
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwAAAQ%3D%3D')/messages(id,subject,from)",
// "value": [
// ]
// }
//
// ------------------------------------------------------------------
// Searching /Inbox/abc/subFolderB
// {
// "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('me')/mailFolders('AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwMAAAA%3D')/messages(id,subject,from)",
// "value": [
// ]
// }
//
// ------------------------------------------------------------------
// Combined Search Results:
// {
// "value": [
// {
// "folderPath": "/Inbox",
// "id": "AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgBGAAADsVyfxjDU406Ic4X7ill8xAcA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA5_vF7TKKdE6bGCRqXyl2PQAAAM6Jj10AAAA=",
// "subject": "A sample email with Amazon in the body",
// "from": {
// "emailAddress": {
// "name": "Chilkat Software",
// "address": "support@chilkatsoft.com"
// }
// }
// },
// {
// "folderPath": "/Inbox/abc/subFolderA/a",
// "id": "AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgBGAAADsVyfxjDU406Ic4X7ill8xAcA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwIAAADn68XtMop0TpsYJGpfKXY9AAAAzombFQAAAA==",
// "subject": "Sample email from admin@chilkat.io",
// "from": {
// "emailAddress": {
// "name": "Chilkat Software",
// "address": "admin@chilkat.io"
// }
// }
// }
// ]
// }
//
End_Procedure