Sample code for 30+ languages & platforms
Zig

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 Zig Downloads

Zig
const std = @import("std");
const chilkat = @import("chilkat");

pub fn main(init: std.process.Init) !void {
    const alloc = init.arena.allocator();

    var success: bool = false;

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    const http = try chilkat.Http.init();
    defer http.deinit();

    // 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).

    http.setAuthToken("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)
    const xml_map = try chilkat.Xml.init();
    defer xml_map.deinit();
    success = if (xml_map.loadXmlFile("qa_data/outlook/folderMap.xml")) true else |_| false;
    if (!success) {
        std.debug.print("Failed to load XML folder map.\n", .{});
        return;
    }

    // We're going to return just the message id, subject, and FROM name/address.
    http.setUrlVar("select", "id,subject,from") catch {};

    // Our search will be for emails with the word "sample" in the subject.
    http.setUrlVar("filter", "contains(subject,'sample')") catch {};

    const json = try chilkat.JsonObject.init();
    defer json.deinit();
    json.setEmitCompact(false);

    const json_combined = try chilkat.JsonObject.init();
    defer json_combined.deinit();
    json_combined.setEmitCompact(false);

    const sb_response = try chilkat.StringBuilder.init();
    defer sb_response.deinit();
    const sb_path = try chilkat.StringBuilder.init();
    defer sb_path.deinit();
    const num_folders = xml_map.getNumChildren();
    var i: i32 = 0;
    var j: i32 = 0;
    var k: i32 = 0;
    while (i < num_folders) {
        xml_map.setI(i);
        sb_path.setString(try xml_map.getChildContent(alloc, "e[i]|k")) catch {};

        if (sb_path.startsWith("/Inbox", true)) {
            std.debug.print("------------------------------------------------------------------\n", .{});
            std.debug.print("Searching {s}\n", .{try sb_path.getAsString(alloc)});

            // Search this mail folder..
            http.setUrlVar("folder_id", try xml_map.getChildContent(alloc, "e[i]|v")) catch {};

            sb_response.clear();
            success = if (http.quickGetSb("https://graph.microsoft.com/v1.0/me/mailFolders/{$folder_id}/messages?$filter={$filter}&$select={$select}", sb_response)) true else |_| false;
            if ((!success) and (http.getLastStatus() == 0)) {
                std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
                return;
            }

            json.loadSb(sb_response) catch {};

            if (http.getLastStatus() != 200) {
                std.debug.print("HTTP response status = {d}\n", .{http.getLastStatus()});
                std.debug.print("{s}\n", .{try json.emit(alloc)});
                std.debug.print("Failed.\n", .{});
                return;
            }

            std.debug.print("{s}\n", .{try json.emit(alloc)});

            // 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.
            //               ]
            //             }

            const num_messages = json.sizeOfArray("value");
            j = 0;
            while (j < num_messages) {
                json.setJ(j);

                // Add this message to the final result set.
                json_combined.setK(k);
                json_combined.updateString("value[k].folderPath", try sb_path.getAsString(alloc)) catch {};
                json_combined.updateString("value[k].id", try json.stringOf(alloc, "value[j].id")) catch {};
                json_combined.updateString("value[k].subject", try json.stringOf(alloc, "value[j].subject")) catch {};
                json_combined.updateString("value[k].from.emailAddress.name", try json.stringOf(alloc, "value[j].from.emailAddress.name")) catch {};
                json_combined.updateString("value[k].from.emailAddress.address", try json.stringOf(alloc, "value[j].from.emailAddress.address")) catch {};
                k = k + 1;

                j = j + 1;
            }
        }

        i = i + 1;
    }

    // Show the final combined JSON search result.
    std.debug.print("------------------------------------------------------------------\n", .{});
    std.debug.print("Combined Search Results:\n", .{});
    std.debug.print("{s}\n", .{try json_combined.emit(alloc)});

    // 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"
    //         }
    //       }
    //     }
    //   ]
    // }
    //
}