How to Permanently Remove Mailbox Items with the Graph API

Permanent Deletion for Message and Other Types of Items from User Mailboxes

On April 1, 2025, Microsoft announced the availability of APIs to permanently delete mailbox items. This news might well have passed you by because the post appeared in the developer blog rather than anything a Microsoft 365 tenant administrator might see.

The APIs are intended to fill in some gaps in Graph API coverage for mailbox items compared to Exchange Web Services (EWS). It’s part of the campaign to remove EWS from Exchange Online by October 2026. An example of where permanent removal of mailbox items is needed is when migrating mailboxes from one tenant to another. After a successful move, the migration utility might clean up by removing items from the source mailbox.

In any case, APIs are now available to permanently delete mail message, mail folder, event, calendar, contact, and contact folder objects.

What Permanent Removal Means

In this context, permanent removal means that no client interface exists to allow the user to recover the message. For example, users can’t use Outlook’s Recover Deleted Items facility to retrieve the deleted items and administrators can’t use the Get-RecoverableItems cmdlet to do likewise (or appear in a report of recoverable items).

The reason why this is so is that when Outlook deletes items in the Deleted Items folder, the items move to the Deletions folder within Recoverable Items. When the API deletes an item, the item moves to the Purges folder. If the item is not subject to a hold, the Managed Folder Assistant will remove it the next item the mailbox is processed. If it is subject to a hold, the item remains in the Purges folder until the hold lapses.

Permanent Removal with the Microsoft Graph API

Two pieces of information are needed to permanently remove a message item using the Graph API: the object identifier for the account that owns the mailbox and the message identifier. Let’s assume that you have a variable containing details of a message:

$Message | Format-List Subject, CreatedDateTime, Id

Subject         : Thank You for Subscribing
CreatedDateTime : 06/05/2022 06:47:28
Id              : AAMkADAzNzBmMzU0LTI3NTItNDQzNy04NzhkLWNmMGU1MzEwYThkNABGAAAAAAB_7ILpFNx8TrktaK8VYWerBwDcIrNcmtpBSZUJ1fXZjZ5iAB_wAYDdAAA3tTkMTDKYRI6zB9VW59QNAAQnaACXAAA=

To delete the item, construct a URI pointing to the message and post the request to the messages endpoint. This example shows where the variables for the user identifier and message identifier are in the URI:

$Uri = ("https://graph.microsoft.com/v1.0/users/{0}/messages/{1}/permanentDelete" -f $UserId, $Message.Id)

$Uri
https://graph.microsoft.com/v1.0/users/eff4cd58-1bb8-4899-94de-795f656b4a18/messages/AAMkADAzNzBmMzU0LTI3NTItNDQzNy04NzhkLWNmMGU1MzEwYThkNABGAAAAAAB_7ILpFNx8TrktaK8VYWerBwDcIrNcmtpBSZUJ1fXZjZ5iAB_wAYDdAAA3tTkMTDKYRI6zB9VW59QNAAQnaACXAAA=/permanentDelete

Invoke-MgGraphRequest -Uri $Uri -Method Post

The Graph API doesn’t ask for confirmation before proceeding to remove the item and it doesn’t provide a status to show that the deletion was successful. The only indication that something happened is found by using the Get-MailboxFolderStatistics cmdlet to see if the items in the Purges folder increase:

Get-MailboxFolderStatistics -FolderScope RecoverableItems -Identity Tony.Redmond | Format-Table Name, ItemsInFolder

Name                                    ItemsInFolder
----                                    -------------
Recoverable Items                                   0
Deletions                                        2135
DiscoveryHolds                                   2543
Purges                                             16
SubstrateHolds                                     12
Versions                                           79

Alternatively, use the MFCMAPI utility to examine the items in the Purges folder. Figure 1 shows that the “Thank you for subscribing” message is in the Purges folder.

MFCMAPI shows the permanently deleted item in the Purges folder.

Permanent deletion with Graph APIs
Figure 1: MFCMAPI shows the permanently deleted item in the Purges folder

Permanent Removal with the Microsoft Graph PowerShell SDK

The Remove-MgUserMessagePermanent cmdlet does the same job as the Graph API request:

Remove-MgUserMessagePermanent -UserId $UserId -MessageId $Message.Id

Once again, there’s no status or confirmation required for the deletion to proceed. The other Microsoft Graph PowerShell SDK cmdlets to permanently remove objects are:

All the cmdlets work in the same way. Deletion is immediate and permanent.

Adding new automation capabilities by extending APIs is always welcome. I just need to find a suitable use case for the new cmdlets.


Need some assistance to write and manage PowerShell scripts for Microsoft 365? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Office 365 for IT Pros eBook bundle.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.