Zig
Zig
Outlook -- Create Map of Folder Paths to IDs
See more Outlook Examples
Recursively descends folders and creates a hashtable of folder paths to IDs. This can be done once at the start of your program (or even less if the map is persisted to a file or database).The reason this is necessary is because folder ID's need to be passed to the Outlook API, and an application will typically be working with folder paths.
Note: This example requires Chilkat v9.5.0.67 or greater.
This example applies to: Exchange Online | Office 365 | Hotmail.com | Live.com | MSN.com | Outlook.com | Passport.com
Chilkat Zig Downloads
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();
// Our folder path --> ID map will be stored in this hash table.
const folder_map = try chilkat.Hashtable.init();
defer folder_map.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");
const sb_response = try chilkat.StringBuilder.init();
defer sb_response.deinit();
// Begin by getting the top-level folders.
http.clearUrlVars();
http.setUrlVar("userPrincipalName", "chilkatsoft@outlook.com") catch {};
success = if (http.quickGetSb("https://graph.microsoft.com/v1.0/users/{$userPrincipalName}/mailFolders", sb_response)) true else |_| false;
if ((!success) and (http.getLastStatus() == 0)) {
std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
return;
}
const json = try chilkat.JsonObject.init();
defer json.deinit();
json.loadSb(sb_response) catch {};
json.setEmitCompact(false);
std.debug.print("Status code = {d}\n", .{http.getLastStatus()});
if (http.getLastStatus() != 200) {
std.debug.print("{s}\n", .{try json.emit(alloc)});
std.debug.print("Failed.\n", .{});
}
// This is our queue/stack of unprocessed folder ID's
// The recursive nature of this example is that we get the
// child folders for each folder ID in the idQueue, which may
// cause additional ID's to be added. We continue until the idQueue
// is empty.
const id_queue = try chilkat.StringArray.init();
defer id_queue.deinit();
const sb_folder_path = try chilkat.StringBuilder.init();
defer sb_folder_path.deinit();
const sb_queue_entry = try chilkat.StringBuilder.init();
defer sb_queue_entry.deinit();
var folder_name: [:0]const u8 = "";
var folder_path: [:0]const u8 = "";
var folder_id: [:0]const u8 = "";
// Prime the map and idQueue with the top-level folders.
var i: i32 = 0;
var num_folders: i32 = json.sizeOfArray("value");
while (i < num_folders) {
json.setI(i);
folder_name = try json.stringOf(alloc, "value[i].displayName");
folder_id = try json.stringOf(alloc, "value[i].id");
sb_folder_path.setString("/") catch {};
sb_folder_path.append(folder_name) catch {};
folder_path = try sb_folder_path.getAsString(alloc);
folder_map.addStr(folder_path, folder_id) catch {};
std.debug.print("{s} --> {s}\n", .{ folder_path, folder_id });
// Push the folder path + id onto the idQueue.
sb_queue_entry.clear();
sb_queue_entry.setNth(0, folder_path, "|", false, false) catch {};
sb_queue_entry.setNth(1, folder_id, "|", false, false) catch {};
id_queue.append(try sb_queue_entry.getAsString(alloc)) catch {};
i = i + 1;
}
// Initial output:
// /Archive --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAG8XunwAAAA=
// /Deleted Items --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEKAAAA
// /Drafts --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEPAAAA
// /Inbox --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA
// /Junk Email --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEiAAAA
// /Outbox --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgELAAAA
// /Sent Items --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEJAAAA
//
// Process the idQueue until it becomes empty. This is the recursive loop.
var parent_folder_path: [:0]const u8 = "";
var parent_folder_id: [:0]const u8 = "";
while (id_queue.getLength() > 0) {
sb_queue_entry.setString(try id_queue.getString(alloc, 0)) catch {};
id_queue.removeAt(0) catch {};
parent_folder_path = try sb_queue_entry.getNth(alloc, 0, "|", false, false);
parent_folder_id = try sb_queue_entry.getNth(alloc, 1, "|", false, false);
http.setUrlVar("id", parent_folder_id) catch {};
success = if (http.quickGetSb("https://graph.microsoft.com/v1.0/users/{$userPrincipalName}/mailFolders/{$id}/childFolders", 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("Status code = {d}\n", .{http.getLastStatus()});
std.debug.print("{s}\n", .{try json.emit(alloc)});
std.debug.print("Failed.\n", .{});
}
i = 0;
num_folders = json.sizeOfArray("value");
while (i < num_folders) {
json.setI(i);
folder_name = try json.stringOf(alloc, "value[i].displayName");
folder_id = try json.stringOf(alloc, "value[i].id");
sb_folder_path.setString(parent_folder_path) catch {};
sb_folder_path.append("/") catch {};
sb_folder_path.append(folder_name) catch {};
folder_path = try sb_folder_path.getAsString(alloc);
folder_map.addStr(folder_path, folder_id) catch {};
std.debug.print("{s} --> {s}\n", .{ folder_path, folder_id });
// Push the folder path + id onto the idQueue.
sb_queue_entry.clear();
sb_queue_entry.setNth(0, folder_path, "|", false, false) catch {};
sb_queue_entry.setNth(1, folder_id, "|", false, false) catch {};
id_queue.append(try sb_queue_entry.getAsString(alloc)) catch {};
i = i + 1;
}
}
// The hash table of mail folder paths --> ID's can be persisted to XML and saved to a file or database (or anywhere..)
const sb_folder_map_xml = try chilkat.StringBuilder.init();
defer sb_folder_map_xml.deinit();
folder_map.toXmlSb(sb_folder_map_xml) catch {};
sb_folder_map_xml.writeFile("qa_data/outlook/folderMap.xml", "utf-8", false) catch {};
// The hash table can be restored from the serialized XML like this:
const ht2 = try chilkat.Hashtable.init();
defer ht2.deinit();
const sb2 = try chilkat.StringBuilder.init();
defer sb2.deinit();
sb2.loadFile("qa_data/outlook/folderMap.xml", "utf-8") catch {};
ht2.addFromXmlSb(sb2) catch {};
// What's the ID for the folder "/Inbox/abc/subFolderA" ?
std.debug.print("id for /Inbox/abc/subFolderA = {s}\n", .{try ht2.lookupStr(alloc, "/Inbox/abc/subFolderA")});
// Final output:
// /Archive --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAG8XunwAAAA=
// /Deleted Items --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEKAAAA
// /Drafts --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEPAAAA
// /Inbox --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEMAAAA
// /Junk Email --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEiAAAA
// /Outbox --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgELAAAA
// /Sent Items --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAgEJAAAA
// /Inbox/abc --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huv8AAAA=
// /Inbox/xyz --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwEAAAA=
// /Inbox/abc/subFolderA --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwAAAQ==
// /Inbox/abc/subFolderB --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwMAAAA=
// /Inbox/abc/subFolderA/a --> AQMkADAwATM0MDAAMS1iNTcwLWI2NTEtMDACLTAwCgAuAAADsVyfxjDU406Ic4X7ill8xAEA5_vF7TKKdE6bGCRqXyl2PQAAAL8huwIAAAA=
//
// ------------------------------------------------------------------------------------------------------
// This example applies to: Exchange Online | Office 365 | Hotmail.com | Live.com | MSN.com | Outlook.com | Passport.com
//
// The Microsoft Graph Outlook Mail API lets you read, create, and send messages and attachments,
// view and respond to event messages, and manage folders that are secured by Azure Active Directory
// in Office 365. It also provides the same functionality in Microsoft accounts specifically
// in these domains: Hotmail.com, Live.com, MSN.com, Outlook.com, and Passport.com.
}