Tcl
Tcl
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 Tcl Downloads
load ./chilkat.dll
set success 0
# This example requires the Chilkat API to have been previously unlocked.
# See Global Unlock Sample for sample code.
set http [new_CkHttp]
# Our folder path --> ID map will be stored in this hash table.
set folderMap [new_CkHashtable]
# 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).
CkHttp_put_AuthToken $http "MICROSOFT_GRAPH_ACCESS_TOKEN"
set sbResponse [new_CkStringBuilder]
# Begin by getting the top-level folders.
CkHttp_ClearUrlVars $http
CkHttp_SetUrlVar $http "userPrincipalName" "chilkatsoft@outlook.com"
set success [CkHttp_QuickGetSb $http "https://graph.microsoft.com/v1.0/users/{$userPrincipalName}/mailFolders" $sbResponse]
if {expr [$success != 1] && [[CkHttp_get_LastStatus $http] == 0]} then {
puts [CkHttp_lastErrorText $http]
delete_CkHttp $http
delete_CkHashtable $folderMap
delete_CkStringBuilder $sbResponse
exit
}
set json [new_CkJsonObject]
CkJsonObject_LoadSb $json $sbResponse
CkJsonObject_put_EmitCompact $json 0
puts "Status code = [CkHttp_get_LastStatus $http]"
if {[CkHttp_get_LastStatus $http] != 200} then {
puts [CkJsonObject_emit $json]
puts "Failed."
}
# 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.
set idQueue [new_CkStringArray]
set sbFolderPath [new_CkStringBuilder]
set sbQueueEntry [new_CkStringBuilder]
# Prime the map and idQueue with the top-level folders.
set i 0
set numFolders [CkJsonObject_SizeOfArray $json "value"]
while {$i < $numFolders} {
CkJsonObject_put_I $json $i
set folderName [CkJsonObject_stringOf $json "value[i].displayName"]
set folderId [CkJsonObject_stringOf $json "value[i].id"]
CkStringBuilder_SetString $sbFolderPath "/"
CkStringBuilder_Append $sbFolderPath $folderName
set folderPath [CkStringBuilder_getAsString $sbFolderPath]
CkHashtable_AddStr $folderMap $folderPath $folderId
puts "$folderPath --> $folderId"
# Push the folder path + id onto the idQueue.
CkStringBuilder_Clear $sbQueueEntry
CkStringBuilder_SetNth $sbQueueEntry 0 $folderPath "|" 0 0
CkStringBuilder_SetNth $sbQueueEntry 1 $folderId "|" 0 0
CkStringArray_Append $idQueue [CkStringBuilder_getAsString $sbQueueEntry]
set i [expr $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.
while {[CkStringArray_get_Length $idQueue] > 0} {
CkStringBuilder_SetString $sbQueueEntry [CkStringArray_getString $idQueue 0]
CkStringArray_RemoveAt $idQueue 0
set parentFolderPath [CkStringBuilder_getNth $sbQueueEntry 0 "|" 0 0]
set parentFolderId [CkStringBuilder_getNth $sbQueueEntry 1 "|" 0 0]
CkHttp_SetUrlVar $http "id" $parentFolderId
set success [CkHttp_QuickGetSb $http "https://graph.microsoft.com/v1.0/users/{$userPrincipalName}/mailFolders/{$id}/childFolders" $sbResponse]
if {expr [$success != 1] && [[CkHttp_get_LastStatus $http] == 0]} then {
puts [CkHttp_lastErrorText $http]
delete_CkHttp $http
delete_CkHashtable $folderMap
delete_CkStringBuilder $sbResponse
delete_CkJsonObject $json
delete_CkStringArray $idQueue
delete_CkStringBuilder $sbFolderPath
delete_CkStringBuilder $sbQueueEntry
exit
}
CkJsonObject_LoadSb $json $sbResponse
if {[CkHttp_get_LastStatus $http] != 200} then {
puts "Status code = [CkHttp_get_LastStatus $http]"
puts [CkJsonObject_emit $json]
puts "Failed."
}
set i 0
set numFolders [CkJsonObject_SizeOfArray $json "value"]
while {$i < $numFolders} {
CkJsonObject_put_I $json $i
set folderName [CkJsonObject_stringOf $json "value[i].displayName"]
set folderId [CkJsonObject_stringOf $json "value[i].id"]
CkStringBuilder_SetString $sbFolderPath $parentFolderPath
CkStringBuilder_Append $sbFolderPath "/"
CkStringBuilder_Append $sbFolderPath $folderName
set folderPath [CkStringBuilder_getAsString $sbFolderPath]
CkHashtable_AddStr $folderMap $folderPath $folderId
puts "$folderPath --> $folderId"
# Push the folder path + id onto the idQueue.
CkStringBuilder_Clear $sbQueueEntry
CkStringBuilder_SetNth $sbQueueEntry 0 $folderPath "|" 0 0
CkStringBuilder_SetNth $sbQueueEntry 1 $folderId "|" 0 0
CkStringArray_Append $idQueue [CkStringBuilder_getAsString $sbQueueEntry]
set i [expr $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..)
set sbFolderMapXml [new_CkStringBuilder]
CkHashtable_ToXmlSb $folderMap $sbFolderMapXml
CkStringBuilder_WriteFile $sbFolderMapXml "qa_data/outlook/folderMap.xml" "utf-8" 0
# The hash table can be restored from the serialized XML like this:
set ht2 [new_CkHashtable]
set sb2 [new_CkStringBuilder]
CkStringBuilder_LoadFile $sb2 "qa_data/outlook/folderMap.xml" "utf-8"
CkHashtable_AddFromXmlSb $ht2 $sb2
# What's the ID for the folder "/Inbox/abc/subFolderA" ?
puts "id for /Inbox/abc/subFolderA = [CkHashtable_lookupStr $ht2 /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.
delete_CkHttp $http
delete_CkHashtable $folderMap
delete_CkStringBuilder $sbResponse
delete_CkJsonObject $json
delete_CkStringArray $idQueue
delete_CkStringBuilder $sbFolderPath
delete_CkStringBuilder $sbQueueEntry
delete_CkStringBuilder $sbFolderMapXml
delete_CkHashtable $ht2
delete_CkStringBuilder $sb2