A reader wondered how they could create a report of folders in an Exchange Online mailbox to include the retention tag assigned to folders. Retention tags mean both mailbox records management (MRM) retention tags (Exchange legacy retention) and Microsoft 365 retention labels. The Managed Folder Assistant (MFA), the component responsible for retention processing of mailboxes, treats both types equally.
Although Microsoft would like customers to transition from Exchange MRM, the older implementation of retention tags still offers significant value that isn’t available in Microsoft 365. The major gaps in Microsoft 365 retention are the ability to move mailbox items to Exchange archive mailboxes and folder-level retention processing (using default folder tags or personal retention tags). You can transition most retention processing to Microsoft 365, but some elements of MRM retention are still required to use these two features. Microsoft tweaks Exchange MRM to make it behave more like Microsoft 365 retention, but the gap remains.
Getting Exchange Retention Tags from Folder Statistics
Our reader used the Get-ExoMailboxFolderStatistics cmdlet to retrieve details of mailbox folders. The DeletePolicy property is one of the properties fetched for each folder. This property stores the name of the retention tag (folder or personal) assigned to the folder. However, the property is blank if the folder is governed by the default delete and default archive tags defined in the MRM policy assigned to the mailbox. An MRM retention policy can have one default (move to) archive tag and one default delete tag. A policy doesn’t have to include default tags.
Script Steps to Report Exchange Retention Tags
To create a complete picture, I did the following:
Run Get-ExoMailboxFolderStatistics to fetch details of the default mailbox folders (like Inbox and Sent Items) plus user created folders (those likely to be exposed in a client for users to apply retention tags to).
$User = Read-Host "Enter name of user mailbox to examine"
$User = Get-ExoMailbox -Identity $User -ErrorAction SilentlyContinue -Properties RetentionPolicy
If (!($User)) { Write-Host ("Can't find mailbox for {0}" -f $User) ; break }
Write-Host ("Checking mailbox folders for {0}" -f $User.DisplayName)
[array]$MailboxFolders = Get-ExoMailboxFolderStatistics -Identity $User.UserPrincipalName | Where-Object {$_.FolderType -eq 'User created' -or $_.FolderType -eq 'Inbox' `
-or $_.FolderType -eq 'SentItems' -or $_FolderType -eq 'DeletedItems' -or $_.FolderType -eq 'JunkEMail' -or $_.FolderType -eq 'Contacts'} | Sort-Object Name
Unfortunately, Exchange Online mailboxes contain a heap of system-generated folders that are marked as user created. I remove these from the folder set. This is the lazy way to remove the folders.
After that, it’s a matter of running down through the folder set to find if the folder has a tag noted. If it does, we report that. If not, we report the default tags. Figure 1 shows the result.
Figure 1: Exchange mailbox folders and MRM retention tags
There’s no obvious way to get the retention tag for individual messages with PowerShell. I asked Glen Scales, an MVP with long experience of developing against Exchange with EWS and the Graph, and he pointed me to a property called Single Value Extended Properties where Exchange stores the retention tag data for messages. Here’s some code to fetch the top 10 messages from the Inbox folder in a mailbox, including the retention data:
$Uri = "https://graph.microsoft.com/v1.0/users('tony.redmond@office365itpros.com')/MailFolders/Inbox/messages/?`$select=ReceivedDateTime,Sender,Subject,IsRead,InternetMessageId,parentFolderId,hasAttachments&`$Top=10&`$expand=SingleValueExtendedProperties(`$filter=(Id%20eq%20'String%20%7B403FC56B-CD30-47C5-86F8-EDE9E35A022B%7D%20Name%20ComplianceTag'))"
$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get
The “normal” properties are obvious in the output:
$data.value[0]
Name Value
---- -----
@odata.etag W/"CQAAABYAAAA3tTkMTDKYRI6zB9VW59QNAAaLOoml"
singleValueExtendedProperties {System.Collections.Hashtable}
sender {emailAddress}
parentFolderId AAMkADAzNzBmMzU0LTI3NTItNDQzNy04NzhkLWNmMGU1MzEwYThkNAAuAAAAAAB_7ILpFNx8TrktaK8VYWerAQBe9CuwLc2fTK7W4...
isRead True
id AAMkADAzNzBmMzU0LTI3NTItNDQzNy04NzhkLWNmMGU1MzEwYThkNABGAAAAAAB_7ILpFNx8TrktaK8VYWerBwBe9CuwLc2fTK7W4...
receivedDateTime 27/07/2023 19:43:43
hasAttachments False
subject Delivery estimate update for your Amazon.co.uk order #026-5997568-1550717
internetMessageId <0102018998e0cc4a-0fef8181-323f-4bb1-b22f-951a6840abe4-000000@eu-west-1.amazonses.com>
The retention tag is in a hash table in Single Value Extended Properties. We can see that the name of the retention tag is “Inbox 7 Year.”
$data.value[0].singleValueExtendedProperties
Name Value
---- -----
value Inbox 7 Year
id String {403fc56b-cd30-47c5-86f8-ede9e35a022b} Name ComplianceTag
Note: retention tag information is only present when an item has been stamped with a tag. Items under the control of a default retention tag (for deletion or archival) don’t have the retention information in their properties. When Managed Folder Assistant processes mailbox items, it applies the settings from default tags to items when if a more specific tag (folder or personal) is absent.
It is possible to fetch the information for every message in a mailbox and report its retention tag. Given the sheer number of messages in mailboxes, I’m not sure if the exercise would be useful in any way, but at least you know it can be done.
Learn more about how the Office 365 applications really work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.
Hello Erica… Nice to see you hanging out here. It’s fair to say that it took quite a while before Microsoft acknowledged the value of MRM and adjusted the documentation. I hold to my position that Microsoft would like people to move off MRM to Microsoft 365 retention… Which is why I have the link to https://practical365.com/exchange-online-retention-m365-retention/ in the article.
Totally agree that it took us awhile to add it. That wasn’t really due to some strategy – one of our community members pointed out that clarity would be helpful to include this guidance in the documentation, so we added it. Really appreciate how much you help the community (including me) through your posts, and this was another great one!
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
Small correction. Microsoft actually encourages customers to use MRM for the scenarios you described: https://learn.microsoft.com/en-us/purview/retention#use-retention-policies-and-retention-labels-instead-of-older-features
Hello Erica… Nice to see you hanging out here. It’s fair to say that it took quite a while before Microsoft acknowledged the value of MRM and adjusted the documentation. I hold to my position that Microsoft would like people to move off MRM to Microsoft 365 retention… Which is why I have the link to https://practical365.com/exchange-online-retention-m365-retention/ in the article.
Totally agree that it took us awhile to add it. That wasn’t really due to some strategy – one of our community members pointed out that clarity would be helpful to include this guidance in the documentation, so we added it. Really appreciate how much you help the community (including me) through your posts, and this was another great one!