Skip to main content

Graph Mailbox Basics with PowerShell Part 1 Folders

I haven't done a basics series for a while but based on some of the questions I've been getting lately and the lack of some good Mailbox specific examples for basic but more complex tasks using the Graph against Exchange Online Mailboxes this seemed like a good series to write.

For all the scripts in this series I'm not going to use any modules or other libraries so everything will be using Invoke-WebRequest and Invoke-RestMethod, while there is nothing wrong with using libraries or modules and a number of advantages in doing so it just keeps the examples as simple and easy to understand as they can be.

Authentication You can't have an article on the Graph without talking about authentication and we are now far from the past where all you needed was a simple username and password and you where off to the races. The basics of Authentication are is that first you will need an Azure App Registration (that has been consented to), there are many pages dedicated to how you can do this  (this is one of the better ones) so I'm not going to dwell too much on this. My simple template script has a function called Get-AccessTokenForGraph which takes a ClientId and RedirectURI and does an interactive login to get the Azure access token. With oAuth there are many other ways of authenticating so if this doesn't fit your needs you just need to plug your own code in the Get-AccessTokenForGraph function.

Get-FolderFromPath

With Exchange the locator (think file path as an analogy) you use to access a Folder programatically is its FolderId. Every Exchange API has it own interpretation of the FolderId starting with the Fid and PidTagEntryId in Mapi, EWS has the EWSid and Graph just has the Id (and the EMS gives a combination of Id's back depending on which cmdlet you use). With the Graph and EWS id's these id's contain the PidTagEntryId with a bunch of other flags that tell the service how to locate and open the folder. However most of the time us humans think of folders in terms of Paths eg if I have a Subfolder of the Inbox a more human reference would be \Inbox\subfolder (language differences aside). So one of the more common methods I use is the Get-FolderFromPath to get a folder (or just the folderid) so you can then work on the Items within that folder or the folder itself. So the method I've always used in EWS is to take the path you want to search for and split in based on the \ character and then do a number of shallow searches of the parent folders until you find the child folder you want. in the Graph this looks something like this

        $RequestURL = $EndPoint + "('$MailboxName')/MailFolders('MsgFolderRoot')/childfolders?"
        $fldArray = $FolderPath.Split("\")
        $PropList = @()
        $FolderSizeProp = Get-TaggedProperty -DataType "Long" -Id "0x66b3"
        $EntryId = Get-TaggedProperty -DataType "Binary" -Id "0xfff"
        $PropList += $FolderSizeProp 
        $PropList += $EntryId
        $Props = Get-ExtendedPropList -PropertyList $PropList 
        $RequestURL += "`$expand=SingleValueExtendedProperties(`$filter=" + $Props + ")"
        #Loop through the Split Array and do a Search for each level of folder 
        for ($lint = 1; $lint -lt $fldArray.Length; $lint++) {
            #Perform search based on the displayname of each folder level
            $FolderName = $fldArray[$lint];
            $headers = @{
                'Authorization' = "Bearer $AccessToken"
                'AnchorMailbox' = "$MailboxName"
            }
            $RequestURL = $RequestURL += "`&`$filter=DisplayName eq '$FolderName'"
            $tfTargetFolder = (Invoke-RestMethod -Method Get -Uri $RequestURL -UserAgent "GraphBasicsPs101" -Headers $headers).value  
            if ($tfTargetFolder.displayname -match $FolderName) {
                $folderId = $tfTargetFolder.Id.ToString()
                $RequestURL = $EndPoint + "('$MailboxName')/MailFolders('$folderId')/childfolders?"
                $RequestURL += "`$expand=SingleValueExtendedProperties(`$filter=" + $Props + ")"
            }
            else {
                throw ("Folder Not found")
            }
        }
So for each folder Step I'm finding the intermediate folder using $filter=DisplayName eq '$FolderName'

To make the results more useful I've included a few extended properties that give me some extra information

The first is the FolderSize, which in Mapi is the PidTagMessageSizeExtended property on the folder 

The second is the pidTagEntryId (PR_EntryId)property which I added in so I could easily convert this into the folderId format that is used in the Office365 compliance search eg in Office365 when you do a compliance search you have the ability of using the folderid:xxxx keyword in a Search to limit the search of a Mailbox to one particular folder in a Mailbox. There is a script in https://docs.microsoft.com/en-us/microsoft-365/compliance/use-content-search-for-targeted-collections?view=o365-worldwide which uses the Get-MailboxFolderStatistics cmdlet which I found a little cumbersome so having a simple method like the above can return the id i need for the folder i want. eg this is what the end result looks like when you run the script



The REST request that is generated by the script looks like (if you want to try this in the graph explorer)

https://graph.microsoft.com/v1.0/users('gscales@datarumble.com')
/MailFolders('MsgFolderRoot')/childfolders?
$expand=SingleValueExtendedProperties($filter=(Id%20eq%20'Long%200x66b3')
%20or%20(Id%20eq%20'Binary%200xfff'))
&$filter=DisplayName%20eq%20'inbox'
There are a bunch more things you can do with this type of query eg working with the retention tags on a folder. Or using the FolderId to then process the Items within that folder. The reason i started with this function is for me its always a jumping off point for starting working with mailbox data.

Popular posts from this blog

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is.

I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned)

#Define Date to Query
$StartDate = (Get-Date)
$EndDate = (Ge…

EWS Managed API and Powershell How-To series Part 1

I thought I'd start the year with a series of posts that goes back over the basics of using the EWS Managed API from Powershell and provides a modular remarked example that you can easily cut and paste to build your own scripts. Along the way in this series I'll show a whole bunch of examples around specific things.

As a starting point for versions this will be Powershell Version 2.0  and the EWS Managed API 1.1 (which will soon change to 1.2 once released) http://www.microsoft.com/download/en/details.aspx?id=13480.

The starting point for any EWS script your going to write is connecting to Exchange for which there are three important pieces of information you will need. Firstly you need to know the version of Exchange your running in this script its going to be held in the following variable

$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1

Other valid values for Exchange 2007 would be

$ExchangeVersion = [Microsoft.Exchange.WebServices.…

Microsoft Teams Private Chat History Addin for Outlook

Being somebody who is transitioning across from Skype for Business to Teams one of things I missed the most (and found the most frustrating) is the lack of the ability in Outlook and OWA to view the conversation history from Online meetings and private chats in Microsoft Teams. This is especially frustrating when you have an external meeting and your sent an IM that contains some vital information for what you need to do. This information is tracked in your mailbox for compliance reasons in the Teams Chat folder but this folder is hidden so it not accessible to the clients and must be extracted by other means eg. Most people seem to point to doing a compliance search if you need this data https://docs.microsoft.com/en-us/microsoftteams/security-compliance-overview .

Given that the information is in my mailbox and there shouldn't be any privacy concern around accessing it I looked at a few ways of getting access to these TeamsChat messages in OWA and Outlook the first way was using …
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.