The ramblings of a madman addicted to tech

Change all Exchange Online calendar permissions with Powershell

Posted at — Jun 5, 2020

We have a script at work that runs every night and sets the default permissions on all Office 365 calendars to LimitedDetails, or “View availability data with subject and location” as the Microsoft Documentation says.

Sounds simple, right?

Well, it is. Or, rather, it was. But then things started breaking.

First we found out some users didn’t have the “Calendar” default calendar, but only had the italian localized “Calendario” folder. Ok, easy enough, we can work around it with an easy “*calendar*” regex… except every user also has a Calendar Logging hidden folder, so we have to exclude that… still, simple enough: Where-Object { $_.Name -like "*calendar*" -and (-not ($_.Name -like "*calendar*logging")) } and we’re done.

Except no, not really. Because users can import other calendars and they will show up in Outlook in the calendar list… and in the Powershell cmdlets as well, obviously, and they will error out when trying to write permissions to them since they’re not an actual calendar but a link. So, time for another easy workaround: a little Get-MailboxFolderStatistics here, a little Where-Object { $_.FolderType -eq "Calendar" } there and we’re done.

For now, at least. Because, obviously, people can have spaces in their name, right? Well, if only Powershell didn’t break up parameters with spaces… and so we have to combine the user’s identity to the calendar’s identity and wrap it all in quotation marks to ignore the spaces… this one is really easy though: "$($Mailbox.Alias):\$($Calendar.Name)".

Too bad by now the script has grown unreadable, ugly and workaroundish… and we’re not writing Bash here, Powershell is supposed to be readable and easy to comprehend! Ok, time to rewrite the script, this time the right way!

So, here it is, in all it’s glory, a whopping four lines of Powershell that took a month to write and will probably be obsoleted soon since the new Exchange Online V2 Powershell module has just been released to GA:

foreach ($Mailbox in $(Get-Mailbox)) {
  $Calendar = Get-MailboxFolderStatistics -Identity $Mailbox.Identity -FolderScope Calendar | Where-Object { $_.FolderType -eq "Calendar" }
  $CalendarIdentity = "$($Mailbox.Alias):\$($Calendar.Name)"
  Set-MailboxFolderPermission -Identity "$CalendarIdentity" -User Default -AccessRights LimitedDetails

This snippet takes into account the possibility that a user has multiple calendars, the default one of which isn’t just called “Calendar” but can be localized into whatever language Office 365 likes. Oh, and the user can have spaces in its name, of course. Hopefully we’ve caught all corners this time…