Exchange Online Export-Import Graph API Preview

Exchange Online Export-Import Graph API Preview

Hi All,

About two Weeks ago, Microsoft has announced the public preview of the Exchange Export-Import Graph API.

Many of our customers currently rely on APIs powered by Exchange Web Services (EWS) for tasks like Exchange mailbox backup, archiving and migration. However, with the EWS deprecation initiative, customers have been asking for a method built on the Microsoft Graph platform to discover mailbox items, selectively export them and then import these items into Exchange Online mailboxes.

API features We are introducing a solution that includes several valuable features, enabling users to effectively utilize these new APIs:

  • Discovery into Mailbox Hierarchy: The APIs allow drilling down into the mailbox hierarchy, including mailbox folders, child folders, and individual mailbox items.
  • Agnostic to the type of mailbox items: Our solution identifies and supports all types of mailbox items, such as messages, contacts, and calendar items, given that they fall under the IPM subtree (refer to IPM Subtree | Microsoft Learn for more information).
  • Support for Archive Mailboxes: Our solution provides support for both users primary mailboxes and their In-Place Archive mailboxes.
  • Folder Management: Users can create, update, and delete mailbox folders, allowing flexibility in modifying mailbox folder structures.
  • Extended Properties: Our solution enables support for single-value and multi-value extended properties associated with mailbox folders and items. These properties allow storing and accessing custom data that is not already exposed in the Microsoft Graph API metadata (refer to Outlook extended properties overview – Microsoft Graph v1.0 | Microsoft Learn for more information).
  • Granular Permission Scopes: We ensure controlled access for applications and users, allowing them to read, export, and import their Exchange mailbox data based on their specific use cases. View the documentation here.

Note: These APIs currently do not support Public Folders.

Already Supported Graph Functions

A lot of these Graph Functions like Folder and Item Management, already exist in current Graph API’s. I’ve documented some basic Functionality here some time ago:

Entra App registration

I’ve created an Entra Application registration

Added the Redirect URI

Addet the Certificate for Authentication

Added the Application Permissions:

  • Mail.Read
  • MailboxFolder.Read.All
  • MailboxFolder.ReadWrite.All
  • MailboxItem.ImportExport.All
  • MailboxItems.Read.All
  • User.Read.All

Get AccessToken

I’ve used the PSMSALNet to aquire the Access Token.

Note that PSMSALNet requires PowerShell 7.4 or newer

###############################################################################
# Get Access Token using App Permission with a Certificate
###############################################################################
#Setting up the Variables for all Examples
Import-Module PSMSALNet
$TenantId = "46bbad84-29f0-4e03-8d34-f6841a5071ad" #Icewolfch.onmicrosoft.com
$AppID = "5107c0b7-477e-4af1-bf4c-222f492c1c12" #EXOExportImport
$RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
$CertificateThumbprint = "A3A07A3C2C109303CCCB011B10141A020C8AFDA3"

#Get Access Token
$Certificate = Get-ChildItem -Path cert:\CurrentUser\my\$CertificateThumbprint
$HashArguments = @{
   ClientId = $AppID
   ClientCertificate = $Certificate
   TenantId = $TenantId
   Resource = "GraphAPI"
}
$Token = Get-EntraToken -ClientCredentialFlowWithCertificate @HashArguments
$AccessToken = $Token.AccessToken
$AccessToken

Check Access Token

There are several ways to check the Access Token. Ive used the PowerShell Module JWTDetails

###############################################################################
# Check Access JWT Token
###############################################################################
# In Browser https://jwt.ms/
#Install-PSResource -Name JWTDetails
#Get-InstalledPSResource -Name JWTDetails
Get-JWTDetails $AccessToken

Exchange Settings

To get the ExchangeMailboxId required by some of the following Querys, you need to use this API. As you can see, it also supports Archive Mailboxes.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) User.Read.All User.ReadWrite.All
Delegated (personal Microsoft account) Not supported. Not supported.
Application User.Read.All User.ReadWrite.All
###############################################################################
# exchangeSettings resource type
# https://learn.microsoft.com/en-us/graph/api/resources/exchangesettings?view=graph-rest-beta
###############################################################################
#Mailbox without Archive
$Mailbox = "a.bohren@icewolf.ch"
$URI = "https://graph.microsoft.com/beta/users/$Mailbox/settings/exchange"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result | fl

#Mailbox with Archive
$Mailbox = "m.muster@icewolf.ch"
$URI = "https://graph.microsoft.com/beta/users/$Mailbox/settings/exchange"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result | fl

Exchange

If you check with Exchange Online PowerShell you can see the Format:

MBX:<ExchangeGUID or ArchiveGUID>@<Tenantid>

Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -ShowBanner:$false
Get-Mailbox -Identity m.muster -Archive | fl *guid*

Folder Management

List Folders

List Folders of a specific Mailbox or Archive Mailbox (Only Folders from “Top of Information Store” or “IPM_Subtree”). It will give you back the ID of the Folder - similar to EWS.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.ImportExport Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.ImportExport.All Not available.
###############################################################################
# List Folders
# https://learn.microsoft.com/en-us/graph/api/mailbox-list-folders?view=graph-rest-beta&tabs=http
###############################################################################
#GET /admin/exchange/mailboxes/{mailboxId}/folders
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.Value
#https://graph.microsoft.com/beta/admin/exchange/mailboxes/MBX:584e83eb-c967-4b4a-9fba-227fab424dbd@46bbad84-29f0-4e03-8d34-f6841a5071ad/folders?$select=id,displayName,childFolderCount,totalItemCount

Create Folder

This Example shows you how to create a Folder.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxFolder.ReadWrite Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxFolder.ReadWrite.All Not available.
###############################################################################
# Create mailboxFolder
# https://learn.microsoft.com/en-us/graph/api/mailbox-post-folders?view=graph-rest-beta&tabs=http
###############################################################################
#POST /admin/exchange/mailboxes/{mailboxId}/folders/inbox/childFolders
#POST https://graph.microsoft.com/beta/admin/exchange/mailboxes/MBX:e0648f21@aab09c93/folders
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/Inbox/childFolders"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Body = @"
{
  "displayName": "Announcements",
  "type": "IPF.Note",
  "singleValueExtendedProperties": [
        {
            "id": "String 0x3001",
            "value": "Announcements"
        }
    ]
}
"@
$Result = Invoke-RestMethod -Method "POST" -Uri $URI -Body $Body -Headers $Headers -ContentType $ContentType
$Result

Get mailboxFolder

This Example shows you how to get a specific Folder (based on FolderID)

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxFolder.Read MailboxFolder.ReadWrite
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxFolder.Read.All MailboxFolder.ReadWrite.All
###############################################################################
# Get mailboxFolder
# https://learn.microsoft.com/en-us/graph/api/mailboxfolder-get?view=graph-rest-beta&tabs=http
###############################################################################
#GET /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}
#GET /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/childFolders/{mailboxFolderId}
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = "AAMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYzLWQyMjI5YzMyYTY3OAAuAAAAAABTq53BPRd5QLt7lLR88XvbAQAz0IL1wr3xRKNiSJ254HvqAASS-E4rAAA="
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderID"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result

Update mailboxFolder

This Example shows you how to Update the Display Name of a Folder.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxFolder.ReadWrite Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxFolder.ReadWrite.All Not available.
###############################################################################
# Update mailboxFolder
# https://learn.microsoft.com/en-us/graph/api/mailboxfolder-update?view=graph-rest-beta&tabs=http
###############################################################################
#PATCH /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}
#PATCH /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/childFolders/{mailboxFolderId}
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = "AAMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYzLWQyMjI5YzMyYTY3OAAuAAAAAABTq53BPRd5QLt7lLR88XvbAQAz0IL1wr3xRKNiSJ254HvqAASS-E4rAAA="
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderID"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
#0x3001 PR_DISPLAY_NAME
$Body = @"
{
  "displayName": "Announcements Update",
  "singleValueExtendedProperties": [
        {
            "id": "String 0x3001",
            "value": "Announcements Update"
        }
    ]
}
"@
$Result = Invoke-RestMethod -Method "PATCH" -Uri $URI -Body $Body -Headers $Headers -ContentType $ContentType
$Result

Delete mailboxFolder

This Example shows you how to delete a Mailbox Folder.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxFolder.ReadWrite Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxFolder.ReadWrite.All Not available.
###############################################################################
# Delete mailboxFolder
# https://learn.microsoft.com/en-us/graph/api/mailbox-delete-folders?view=graph-rest-beta&tabs=http
###############################################################################
#DELETE /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/$ref
#DELETE /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/childFolders/{mailboxFolderId}/$ref
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = "AAMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYzLWQyMjI5YzMyYTY3OAAuAAAAAABTq53BPRd5QLt7lLR88XvbAQAz0IL1wr3xRKNiSJ254HvqAASS-E4rAAA="
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderID"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "DELETE" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result

List childFolders

This Example shows you how to List the child Folders of a specific Mailbox Folder. You can use the Default Foldernames (Inbox, SentItems, Calendar, Contacts or the FolderID).

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxFolder.Read MailboxFolder.ReadWrite
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxFolder.Read.All MailboxFolder.ReadWrite.All
###############################################################################
# List childFolders
# https://learn.microsoft.com/en-us/graph/api/mailboxfolder-list-childfolders?view=graph-rest-beta&tabs=http
###############################################################################
#GET /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/childFolders
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = ""
#$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderID/childFolders"
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/Inbox/childFolders"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.Value

Item Management

List items

This Example shows you how to List the Items in a specific Folder. As you can see, you only get the ID of the Object and CreateDate, ModifyDate, type and Size. No Subject, no Body.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.Read Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.Read.All Not available.
###############################################################################
# List items
# https://learn.microsoft.com/en-us/graph/api/mailboxfolder-list-items?view=graph-rest-beta&tabs=http
###############################################################################
#GET /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/items
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
#$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderId/items"
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/Inbox/items"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.Value

Get mailboxItem

This Example shows you how to get a specific Item in a specific Folder. You only get some meta Information about the Item.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.Read Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.Read.All Not available.
###############################################################################
# Get mailboxItem
# https://learn.microsoft.com/en-us/graph/api/mailboxitem-get?view=graph-rest-beta&tabs=http
###############################################################################
#GET /admin/exchange/mailboxes/{mailboxId}/folders/{mailboxFolderId}/items/{mailboxItemId}
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = "AQMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYAMy1kMjIBOWMzMmE2NzgALgAAA1OrncE9F3lAu3uUtHzxe9sBAIAjf8qBKDxLtlFnOlm0V04AAAIBDAAAAA==" #Inbox
$ItemId = "AAMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYzLWQyMjI5YzMyYTY3OABGAAAAAABTq53BPRd5QLt7lLR88XvbBwCAI3-KgSg8S7ZRZzpZtFdOAAAAAAEMAAAz0IL1wr3xRKNiSJ254HvqAASNnpV6AAA="
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/folders/$FolderId/items/$ItemId"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result

Get singleValueLegacyExtendedProperty

You still can’t get Items in the AssociatedItems Folder. But now you can get some MAPI Properties with the following Query.

Outlook extended properties overview

Format Example Description
“{type} {guid} Name {name}” “String {8ECCC264-6880-4EBE-992F-8888D2EEAA1D} Name TestProperty” Identifies a property by the namespace (the GUID) it belongs to, and a string name.
“{type} {guid} Id {id}” “Integer {8ECCC264-6880-4EBE-992F-8888D2EEAA1D} Id 0x8012” Identifies a property by the namespace (the GUID) it belongs to, and a numeric identifier.
“{type} {proptag}” “String 0x4001” Identifies a predefined property by its property tag.

Permissions

Supported resource Delegated (work or school account) Delegated (personal Microsoft account) Application
calendar Calendars.Read Calendars.Read Calendars.Read
contact Contacts.Read Contacts.Read Contacts.Read
contactFolder Contacts.Read Contacts.Read Contacts.Read
event Calendars.Read Calendars.Read Calendars.Read
group calendar Group.Read.All Not supported Not supported
group event Group.Read.All Not supported Not supported
group post Group.Read.All Not supported Group.Read.All
mailFolder Mail.Read Mail.Read Mail.Read
message Mail.Read Mail.Read Mail.Read
Outlook task Tasks.Read Tasks.Read Not supported
Outlook task folder Tasks.Read Tasks.Read Not supported
###############################################################################
# Get singleValueLegacyExtendedProperty
# https://learn.microsoft.com/en-us/graph/api/singlevaluelegacyextendedproperty-get?view=graph-rest-beta&tabs=http
###############################################################################
#GET /me/messages/{id}?$expand=singleValueExtendedProperties($filter=id eq '{id_value}')
#GET /users/{id|userPrincipalName}/messages/{id}?$expand=singleValueExtendedProperties($filter=id eq '{id_value}')
#GET /me/mailFolders/{id}/messages/{id}?$expand=singleValueExtendedProperties($filter=id eq '{id_value}')
$Mailbox = "a.bohren@icewolf.ch"
$MessageID = "AQMkADU4NGU4M2ViLWM5NjctNGI0YS05ZmJhLTIyADdmYWI0MjRkYmQARgAAAzqJ2GWaRBxKv-EJWOBGbRAHAEZu88iLm85MjHqnrJ10b8oAAAIgiwAAAcb9AhgmYESSPal9iQNu6wAGS204OwAAAA=="
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}

#PR_MESSAGE_CLASS
$URI = "https://graph.microsoft.com/beta/users/$Mailbox/messages/$MessageID/?`$expand=singleValueExtendedProperties(`$filter=id eq 'string 0x001A')"
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.singleValueExtendedProperties | fl

#DKIM Signature
$URI = "https://graph.microsoft.com/beta/users/$Mailbox/messages/$MessageID/?`$expand=singleValueExtendedProperties(`$filter=id eq 'String {00020386-0000-0000-C000-000000000046} Name dkim-signature')"
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.singleValueExtendedProperties | fl

#MessageSize
$URI = "https://graph.microsoft.com/beta/users/$Mailbox/messages/$MessageID/?`$expand=singleValueExtendedProperties(`$filter=id eq 'Long 0x0E08')"
$Result = Invoke-RestMethod -Method "GET" -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.singleValueExtendedProperties | fl

These Querys also work in Graph Explorer. Obviously, you will need to change the Emailadress and the ItemId.

#PR_MESSAGE_CLASS
https://graph.microsoft.com/beta/users/a.bohren@icewolf.ch/messages/AQMkADU4NGU4M2ViLWM5NjctNGI0YS05ZmJhLTIyADdmYWI0MjRkYmQARgAAAzqJ2GWaRBxKv-EJWOBGbRAHAEZu88iLm85MjHqnrJ10b8oAAAIgiwAAAcb9AhgmYESSPal9iQNu6wAGS204OwAAAA==/?$expand=singleValueExtendedProperties($filter=id eq 'string 0x001A')

#DKIM Signature
https://graph.microsoft.com/beta/users/a.bohren@icewolf.ch/messages/AQMkADU4NGU4M2ViLWM5NjctNGI0YS05ZmJhLTIyADdmYWI0MjRkYmQARgAAAzqJ2GWaRBxKv-EJWOBGbRAHAEZu88iLm85MjHqnrJ10b8oAAAIgiwAAAcb9AhgmYESSPal9iQNu6wAGS204OwAAAA==/?$expand=singleValueExtendedProperties($filter=id eq 'String {00020386-0000-0000-C000-000000000046} Name dkim-signature')

#MessageSize
https://graph.microsoft.com/beta/users/a.bohren@icewolf.ch/messages/AQMkADU4NGU4M2ViLWM5NjctNGI0YS05ZmJhLTIyADdmYWI0MjRkYmQARgAAAzqJ2GWaRBxKv-EJWOBGbRAHAEZu88iLm85MjHqnrJ10b8oAAAIgiwAAAcb9AhgmYESSPal9iQNu6wAGS204OwAAAA==/?$expand=SingleValueExtendedProperties($filter=id eq 'Long 0x0E08')

Export Mailbox Items

This Example shows you how to Export a Mailbox Item. You can add multipe ItemIds in one Query

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.ImportExport Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.ImportExport.All Not available.
###############################################################################
# mailbox: exportItems
# https://learn.microsoft.com/en-us/graph/api/mailbox-exportitems?view=graph-rest-beta&tabs=http
###############################################################################
# POST /admin/exchange/mailboxes/{mailboxId}/exportItems
# POST https://graph.microsoft.com/beta/admin/exchange/mailboxes/MBX:e0643f21@a7809c93/exportItems
$MailboxId = "MBX:584e83eb-c967-4b4a-9fba-227fab424dbd@46bbad84-29f0-4e03-8d34-f6841a5071ad" #a.bohren@icewolf.ch
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/exportItems"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Body = @"
{
    "itemIds": [
        "AQMkADU4NGU4M2ViLWM5NjctNGI0YS05ZmJhLTIyADdmYWI0MjRkYmQARgAAAzqJ2GWaRBxKv-EJWOBGbRAHAEZu88iLm85MjHqnrJ10b8oAAAIgiwAAAcb9AhgmYESSPal9iQNu6wAGS204OwAAAA=="
    ]
}
"@
$Result = Invoke-RestMethod -Method "POST" -Body $Body -Uri $URI -Headers $Headers -ContentType $ContentType
$Result.Value | fl

#Save Data to File
$Result.value.data | Set-Content -Path "C:\Temp\data.txt"

Import Session

This Example shows you how to create a Import Session for a specific Mailbox. It will return you the ImportURL.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.ImportExport Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.ImportExport.All Not available.
###############################################################################
# mailbox: createImportSession
# https://learn.microsoft.com/en-us/graph/api/mailbox-createimportsession?view=graph-rest-beta&tabs=http
###############################################################################
# POST /admin/exchange/mailboxes/{mailboxId}/createImportSession
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$URI = "https://graph.microsoft.com/beta/admin/exchange/mailboxes/$MailboxId/createImportSession"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Result = Invoke-RestMethod -Method "POST" -Uri $URI -Headers $Headers
$ImportURL = $Result.importUrl
$ImportURL

Import Mailbox Item

This Example shows you how to Import a Mailbox Item to a Mailbox.

Permission type Least privileged permissions Higher privileged permissions
Delegated (work or school account) MailboxItem.ImportExport Not available.
Delegated (personal Microsoft account) Not supported. Not supported.
Application MailboxItem.ImportExport.All Not available.
###############################################################################
# mailbox: Import Mailbox Item
#https://learn.microsoft.com/en-us/graph/import-exchange-mailbox-item
###############################################################################
#POST https://outlook.office365.com/api/gbeta/Mailboxes('MBX:e0643f21@a7809c93')/importItem?authtoken=eyJhbGciOiJSUzI1NiIsImtpZCI6IjFTeXQ1b
$MailboxId = "MBX:18f5d451-048e-4f8c-a663-d2229c32a678@46bbad84-29f0-4e03-8d34-f6841a5071ad" #m.muster@icewolf.ch
$FolderId = "AAMkADE4ZjVkNDUxLTA0OGUtNGY4Yy1hNjYzLWQyMjI5YzMyYTY3OAAuAAAAAABTq53BPRd5QLt7lLR88XvbAQAz0IL1wr3xRKNiSJ254HvqAAK-yWB4AAA=" #Sub5_Demo
$Content = Get-Content -Path "C:\Temp\data.txt"
$Body = @"
{
    "FolderId": "$FolderID",
    "Mode": "create",
    "Data": "$Content"
}
"@

$Result = Invoke-RestMethod -Method "POST" -Uri $ImportURL -Body $Body -ContentType "application/json" #-Headers $Headers
$Result | fl

An Email has been restored to another Mailbox.

Summary

I’ve explained an tested how to use the public preview of the Exchange Online Export-Import Graph API. It’s a welcome change and i guess a lot of 3rd Party Applications specialized in this Field have waited on these Features. I guess, we will see 3rd Party Applications will adopt these API’s and integrate it in theyr solutions.

As you can see everything is based on FolderId and ItemId. An Application has to build the Folder hierarchy and Export each Item in each folder. In case of a Restore into a new or diffrent Mailbox, the challenge is to create the Mailbox Folder hierarchy and have a translation Table between the old and new FolderId’s.

Another concern is the Performance of the API. One comment pointed out, that in EWS there are 27 concurrent connections allowed in Exchange Online in Graph there are only 4. I guess until the GA Release the Throttling will have sorted out.

Regards
Andres Bohren

Exchange Logo

PowerShell Logo