Tuesday, April 25, 2017

Using the Office365/Exchange 2016 REST API to access Mailbox data using PowerShell part 3

In Part 1 of this continuing series I looked at the basics of accessing a Mailbox using the new REST api in PowerShell with Exchange and in Part 2 accessing all the mailboxes in a tenant as an Administrative application using Certificate authentication. In this installment I've expanded the REST PowerShell module to encompass most of the common data operations like enumerating Folder and Items.

Getting a folder from Path

A common thing you might want to do with a script that accesses a Mailbox is access a non default folder eg say a folder that a user or application has created in the Inbox. To access a folder with the REST api you need to first know the Id of that particular folder. With the WellKnownFolders in a Mailbox you can use the constants such as Inbox,SentItems etc but for non default folders you need some code that will first find the Id of the Folder by searching for the folder in question in each of the parent folders. I've added a function in the Rest module called Get-FolderFromPath which will take the Path of the folder you want to access and break down and search for each of the folder in the Path and then return the target Folder eg

Enumerating the Folders in a Mailbox

If you want to enumerate all the Folders in a Mailbox in EWS you could do a deep traversal with the  FindFolders operation which would return all the folder paged in lot of 1000. With the REST API you need to traverse each of the ChildFolders separately to return all the folders. With Exchange in EWS there where 4 different strongly typed Folder objects Mail, Tasks, Contacts and Calendar, with EWS all of these where returned with the FindFolder operation. However with the REST API only Mail Folders are returned. With the Calendar, Contacts and Tasks folder you need to use the endpoints for those folder types which also have different permissions associated. This is done so you can have apps that can access all the calendar or contact folders in a Mailbox without the need to have permissions to traverse the Mail folders (and via verse).So if your migrating an existing script its going to requires a slightly different approach from what you may have traditionally done in other API's when doing this type of enumeration.

For enumerating all the Folders in a Mailbox I have created the Get-AllMailFolders function which also appends in the FolderPath as a value add eg

Enumerating Items in a Folder

Once you have retrieved a folder the next logical thing most people want to do is enumerate the Items in that Folder. To do this I've created a few different functions in the module the most common of those is the Get-FolderItems function. This function will either take the JSON Folder object or the path of the folder you want to access and then return each of the Items so you can use it like the following

this function handles paging of the folder Items in 1000 Item pages with involves using the @odata.nextLink return value and $Top and $Skip tokens from the response.

Enumerating All Items in a Mailbox

One of the things the REST API exposes easily that EWS didn't is the ability to enumerate all Items in a Mailbox using the AllItems WellKnowFolder name. I've created a function that exposes that endpoint for the AllItems folder eg

 Get-AllMailboxItems -MailboxName gscales@datarumble.com -AccessToken $tk

Enumerating Focussed Inbox Items

The replacement to Clutter in Office365 as a way of addressing Inbox overload in Exchange is the Focused Inbox which takes advantage of the rapid development of machine learning. From a programmatic point of view the focused Inbox is exposed as a Property InferenceClassification on a Message. So to show just focused Inbox items you can use the Filter token to query for those items that are just equal to focused eg

"Inbox/messages/?`$select=ReceivedDateTime,Sender,Subject,IsRead,InferenceClassification`&`$Top=1000`&`$filter=InferenceClassification eq 'Focused'"

I've created a function called Get-FocusedInboxItems for this which you can use like the following

Get the Mailbox GUID

One last thing that comes in handy sometimes when trying to correlate data is the mailbox GUID for different users. This is now more easily available in the REST api then it was in EWS using the users endpoint. I've put together a simple function to use this called Get-MailboxUser and it can be used like

The updated REST module can be found on GitHub here https://github.com/gscales/Powershell-Scripts/blob/master/RestHttpClientMod.ps1

Thursday, April 06, 2017

Using the Archive Item operation in EWS

As there has been a bit of talk about archiving lately and the new Archive Folder vs the Online Archive in Office365 https://support.office.com/en-us/article/Archive-in-Outlook-2016-for-Windows-25f75777-3cdc-4c77-9783-5929c7b47028?ui=en-US&rs=en-US&ad=US and https://www.petri.com/exchange-online-archive-options .I'd though I'd do a post about the Archive Item operation in EWS which was introduced in Exchange 2013 and is an interesting lever for admins to use if they want to look a manually archiving items to a Mailboxes online archive without using Archive Policies. The Archive Item operation is basically designed to allow you to move items from the Primary to the Online Archive more easily instead of having to batch a Move operation. To use this operation you need to enumerate the Items you want to archive (using a search filter or other restriction) and then provide that as one of the inputs for archive Items as longs as the folder where the Items are being archived from. The only real catch I've found when using it is that you need to use Impersonation or the Automated folder creation in the Archive doesn't seem to happen.

I've created a script that allows you to query a Mailbox folder using an AQS query based on the item received date and then invoke the Archive Items operation on those items and put this up on GitHub here https://github.com/gscales/Powershell-Scripts/blob/master/ArchiveItems.ps1

This script requires EWS impersonation https://msdn.microsoft.com/en-us/library/office/dn722376(v=exchg.150).aspx to run

To run the script you pass in the Mailbox you want to run the script against, the FolderPath where the Items exist that you want to archive and the Date of the Items you want to archive from. Eg to archive items older then one year you would run

Invoke-ArchiveItems -MailboxName user@domain.onmicrosoft.com -FolderPath "\Clutter" -queryTime (Get-Date).AddDays(-365)