Delegate Access and Mailbox Permissions Bring Us to Folder Permissions
Two recent posts about Outlook Mobile supporting delegate access to Exchange Online mailboxes and reporting mailbox permissions bring us to the topic of folder permissions. Outlook Mobile uses full access permission to access delegate mailboxes and the report captures this information. But Exchange Online has supported folder-level permissions for many years (here’s a 2006 blog based on Exchange 2003 SP2) and it’s common to find these permissions in use, especially with Outlook desktop.
Outlook Delegate Access
Folder-level permissions have been core to Outlook’s ability to satisfy the traditional manager-assistant work model where the assistant takes care of the manager’s inbox and calendar. This capability is still supported and documented today for Outlook ProPlus and Outlook 2019.
The option to assign delegate access to mailbox folders in Outlook ProPlus is in the backstage area (Figure 1). Alternatively, you can search for “delegates” and Outlook will find it for you.
Figure 1: Delegate options in the Outlook back stage
Setting Outlook Delegate Permissions
Figure 2 shows delegates (left – none are listed because I’m in the process of assigning one) and folder permissions (right). In this case, I’ve selected a user to act as a delegate and chosen the permissions I wanted to assign. When ready, click OK to save the delegated permissions.
Figure 2: Granting someone delegate access to folders with Outlook
When someone assigns folder permissions to a delegate, Exchange Online creates and sends an automatic notification to the delegate to inform them that they can now open the folders (Figure 3).
Figure 3: Email notification to a delegate
The support article emphasizes that you should grant Folder visible permission on the root folder of the your mailbox to delegates. This is especially important if the delegate wants to access the delegated folders as shared folders in OWA. In Outlook, delegates should add the mailbox to their profile.
Steps to Script a Folder-Level Access Report
Just like it’s good advice to run a periodic check of
mailbox permissions, it’s good to validate that everyone who is assigned
permission over folders outside their own mailbox still need that permission. Exchange
Online doesn’t come with a report to tell us what folder permissions are in
place, so we need to do this with PowerShell.
The Get-MailboxPermission cmdlet fetches permissions
for a mailbox. Its counterpart, Get-MailboxFolderPermission, does the
same for a folder. Conceptually, the steps to create a report are
straightforward:
Find a set of mailboxes to check.
Find the folders in each mailbox to check. Exchange Online mailboxes often hold hundreds of folders. We only need to check folders that are commonly delegated, like the Inbox, Sent Items, and Calendar.
Fetch the permissions for each folder and extract delegated assignments to users who aren’t the mailbox owner.
Report any delegated access to the selected folders.
You could use the Get-Mailbox, Get-MailboxFolderStatistics, and Get-MailboxFolderPermission cmdlets to create the report. To be a little different, I used the new REST cmdlets because an equivalent is available for each of the three cmdlets listed above (Get-ExoMailbox, Get-ExoMailboxFolderStatistics, and Get-ExoMailboxFolderPermission).
Differences in REST Cmdlets
Using the REST cmdlets means that things run faster, especially
when you’re dealing with hundreds or thousands of mailboxes. This is important,
especially when the cmdlets are all quite demanding in terms of system
resources.
The downside is that sometimes the REST cmdlets return data in different formats to their Remote PowerShell counterparts. For example, after retrieving permissions for a folder with Get-MailboxFolderPermission, you might want to fetch the name of the delegated user. If the variable $Permission holds the retrieved permission, the name of the user is available as $Permission.User.DisplayName, but it’s $Permission.User with Get-ExoMailboxPermission. It’s the detail that counts when you move from one set of cmdlets to another!
CSV Output
You can grab a copy of the script from GitHub. Its output is a CSV file (Figure 4) that might reveal some interesting delegations. For instance, I found an entry for a user (Michael Harty) that no longer exists in my tenant.
Outlook Mobile to Support Folder-Level Permissions
Microsoft says that Outlook Mobile will support folder-level permissions in the future to remove the need to grant complete access to everything in a delegate mailbox. This is a good step forward that will be welcome by those who don’t really want to expose everything they have just to let someone else manage part of their email.
Using PowerShell like this proves that it’s a great skill for any Office 365 administrator to have. You can find out a lot more about using PowerShell to manage Office 365 in the Office 365 for IT Pros eBook. Join our happy band of subscribers today!
It’s sad that you received errors. But think of it as an opportunity for you to debug and fix whatever problem you encountered. As you didn’t say what problem you met, we can’t do anything for you (no one in the Office 365 for IT Pros team is equipped with telepathy). And anyway, we write PowerShell to demonstrate principals, not as bullet-proof examples of how to write scripts. See https://office365itpros.com/2019/11/28/why-do-we-write-powershell-like-we-do/ for more detail on this point.
{"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}
received errors on the script
It’s sad that you received errors. But think of it as an opportunity for you to debug and fix whatever problem you encountered. As you didn’t say what problem you met, we can’t do anything for you (no one in the Office 365 for IT Pros team is equipped with telepathy). And anyway, we write PowerShell to demonstrate principals, not as bullet-proof examples of how to write scripts. See https://office365itpros.com/2019/11/28/why-do-we-write-powershell-like-we-do/ for more detail on this point.
Reminds me something I wrote a while back but I haven’t updated my script for Exchange Online but I think it could help for tenant to tenant migrations as folder level permissions are often missed… depending on the tool that is… Thanks for the effort as always. https://practical365.com/preliminary-permission-clean-up-steps-for-a-successful-mailbox-migration/