Table of Contents
Set Calendar Permission to Allow Organization Users to See Limited Details
In September 2021, I wrote about how to set the calendar permission for mailboxes to allow users within the organization to view event titles and locations. In the article, I discuss how to use the Set-MailboxFolderPermission cmdlet to update the access rights assigned to the “default user” from availability only to limited details. The permission assigned to the default user is the one used if a more specific permission is unavailable. By allowing more access to a user calendar for the default user, it means that anyone in the organization can see more information from that user’s calendar. In OWA and the new Outlook for Windows (Monarch) client, the sharing permission is called “can view titles and locations” (Figure 1).
Can view titles and locations means that users who check someone else’s calendar to see event subjects and locations. The default shows only that slots in a calendar are blocked or free.
Calendar Permissions and the Graph
Time passes on and today an alternative solution is available in the form of the Graph calendar permission resource and its methods, plus the associated Microsoft Graph PowerShell SDK cmdlets like Get-MgUserCalendarPermission and Update- MgUserCalendarPermission.
The Get-MailboxFolderPermission and Set-MailboxFolderPermission cmdlets have never been quick, so the question is whether the Graph-based cmdlets are faster at checking and setting calendar permissions.
Testing Performance
I decided to test by writing two scripts. Both scripts fetch user and room mailboxes which use the limited availability permission and update the mailboxes to allow access to limited details.
Both scripts use the Get-ExoMailbox cmdlet to fetch mailbox details. There isn’t a good Graph-based method to fetch mailbox-enabled accounts. Get-MgUser can apply a filter to fetch licensed accounts, but that set won’t include room mailboxes. Get-MgUser can fetch all member accounts, but this set will probably include a bunch of accounts that don’t have mailboxes. In addition, because the script loads the Exchange Online management module to use Get-ExoMailbox, it can also use Set-Mailbox to update a custom attribute with an indicator after processing a mailbox.
Maintaining an indicator in a custom attribute is important because the Get-ExoMailbox command can filter out mailboxes that have the permission set. For instance, if you run the script monthly, it will only process mailboxes created since the last run.
Here’s the Exchange Online script. The Set-MailboxFolderPermission cmdlet requires passing the name of the calendar folder, so there’s some code to figure out the value in different languages.
# Exchange Online version [array]$Mbx = Get-ExoMailbox -RecipientTypeDetails UserMailbox, RoomMailbox -Filter {CustomAttribute10 -ne "OpenCalendar"} -ResultSize Unlimited -Properties Languages | Sort-Object DisplayName Write-Host ("{0} mailboxes found" -f $Mbx.Count) [int]$Updates = 0 ForEach ($M in $Mbx) { # Figure out the name of the Calendar folder in the user's preferred language [array]$Languages = $M.Languages Switch ($Languages[0]) { "en-US" { $CalendarName = "Calendar" } "fr-FR" { $CalendarName = "Calendrier" } "de-DE" { $CalendarName = "Kalender" } "es-ES" { $CalendarName = "Calendario" } "it-IT" { $CalendarName = "Calendario" } "nl-NL" { $CalendarName = "Agenda" } Default { $CalendarName = "Calendar" } } # Build the path to the Calendar folder $CalendarFolder = ("{0}:\{1}" -f $M.UserPrincipalName, $CalendarName) [array]$Data = Get-MailboxFolderPermission -Identity $CalendarFolder | Where-Object {$_.User.usertype.value -eq "Default"} | Select-Object -ExpandProperty AccessRights If ([string]$Data -ne "LimitedDetails") { Write-Host ("Setting LimitedDetails permission for {0}" -f $M.displayName) -ForegroundColor Yellow Set-MailboxFolderPermission -Identity $CalendarFolder -User Default -AccessRights LimitedDetails Set-Mailbox -Identity $M.UserPrincipalName -CustomAttribute10 "OpenCalendar" $Updates++ } Else { # for some reason the custom attribute is not set to reflect the calendar permission, so update it Write-Host "Setting custom attribute for" $M.UserPrincipalName Set-Mailbox -Identity $M.UserPrincipalName -CustomAttribute10 "OpenCalendar" } } Write-Host ("Calendar permission updated for {0} mailboxes" -f $Updates)
Here’s the version using a mixture of Exchange Online and Microsoft Graph PowerShell SDK cmdlet. This code doesn’t need to know anything about language values for folder names because the Graph uses different identifiers.
# Graph version [int]$Updates = 0 [array]$Mbx = Get-ExoMailbox -RecipientTypeDetails UserMailbox, RoomMailbox -Filter {CustomAttribute10 -ne "OpenCalendar"} -ResultSize Unlimited -Properties Languages | Sort-Object DisplayName Write-Host ("{0} mailboxes found" -f $Mbx.Count) ForEach ($M in $Mbx){ [array]$CalendarPermissions = Get-MgUserCalendarPermission -UserId $M.ExternalDirectoryObjectId If ($CalendarPermissions) { $OrgDefault = $null [array]$OrgDefault = $CalendarPermissions | Where-Object {$_.EmailAddress.Name -eq "My Organization"} If ($Permission -notin $OrgDefault.Role) { Write-Host ("Setting Limited Read permission for {1}" -f $M.DisplayName) -ForegroundColor Yellow Try { Update-MgUserCalendarPermission -UserId $M.ExternalDirectoryObjectId ` -Role "LimitedRead" -CalendarPermissionId $OrgDefault.id | Out-Null $Updates++ } Catch { Write-Host ("Failed to update calendar permission for {0}" -f $M.DisplayName) -ForegroundColor Red } Set-Mailbox -Identity $M.ExternalDirectoryObjectId -CustomAttribute10 "OpenCalendar" } Else { Write-Host ("{0} already has the Limited Read permission" -f $M.DisplayName) } } } Write-Host ("Calendar permission updated for {0} mailboxes" -f $Updates)
Here’s the version using a mixture of Exchange Online and Microsoft Graph PowerShell SDK cmdlet. This code doesn’t need to know anything about language values for folder names because the Graph uses different identifiers. I can’t account for why Microsoft decided to call the permission LimitedDetails in Exchange and LimitedRead in the Graph. The different roles available for the Graph are documented online.
# Graph version [int]$Updates = 0 [array]$Mbx = Get-ExoMailbox -RecipientTypeDetails UserMailbox, RoomMailbox -Filter {CustomAttribute10 -ne "OpenCalendar"} -ResultSize Unlimited -Properties Languages | Sort-Object DisplayName Write-Host ("{0} mailboxes found" -f $Mbx.Count) ForEach ($M in $Mbx){ [array]$CalendarPermissions = Get-MgUserCalendarPermission -UserId $M.ExternalDirectoryObjectId If ($CalendarPermissions) { $OrgDefault = $null [array]$OrgDefault = $CalendarPermissions | Where-Object {$_.EmailAddress.Name -eq "My Organization"} If ("LimitedRead" -notin $OrgDefault.Role) { Write-Host ("Setting Limited Read permission for {0}" -f $M.DisplayName) -ForegroundColor Yellow Try { Update-MgUserCalendarPermission -UserId $M.ExternalDirectoryObjectId ` -Role "LimitedRead" -CalendarPermissionId $OrgDefault.id | Out-Null $Updates++ } Catch { Write-Host ("Failed to update calendar permission for {0}" -f $M.DisplayName) -ForegroundColor Red } Set-Mailbox -Identity $M.ExternalDirectoryObjectId -CustomAttribute10 "OpenCalendar" } Else { Write-Host ("{0} already has the Limited Read permission" -f $M.DisplayName) } } } Write-Host ("Calendar permission updated for {0} mailboxes" -f $Updates)
The Measure-Command cmdlet generated the test results, which showed that the Exchange script required 2.84 seconds per mailbox to run. The Graph version was nearly a second faster per mailbox (1.96 seconds). Your mileage might vary.
No Need to Change Unless You Must
Using the Graph SDK cmdlets saves almost a second per mailbox. That doesn’t mean that you should update scripts to rip out and replace the Set-MailboxFolderPermission cmdlet. While it’s important to use code that runs quickly, this kind of script is not something you’re going to run daily. It’s more likely to run on a scheduled basis, such as an Azure Automation runbook, and you won’t notice the extra time.
Besides, the most important contribution to performance in this example is reducing the number of mailboxes to process by maintaining the indicator and using the indicator to filter mailboxes. One cmdlet might be faster than another, but it’s how you use cmdlets in a script that dictates overall performance.
So much change, all the time. It’s a challenge to stay abreast of all the updates Microsoft makes across the Microsoft 365 ecosystem. Subscribe to the Office 365 for IT Pros eBook to receive monthly insights into what happens, why it happens, and what new features and capabilities mean for your tenant.