All scripts
Automation 275
Bulk Set Calendar Permissions From a CSV File
Applies calendar folder permissions across many mailboxes at once from a CSV file, updating existing permissions instead of duplicating them. Handy for onboarding an assistant, standing up a shared team calendar, or rolling out one access level across a department.
Set-BulkCalendarPermission.ps1
<#
.SYNOPSIS
Sets calendar folder permissions on a list of mailboxes from a CSV file.
.DESCRIPTION
Reads a CSV of mailbox, delegate user, and access rights, then applies
Add-MailboxFolderPermission or Set-MailboxFolderPermission in Exchange Online
to each mailbox's Calendar folder. Existing permissions for the same user are
updated instead of duplicated. Useful for onboarding a new assistant, setting
up a shared team calendar, or rolling out one standard access level across a
department in one pass instead of clicking through Outlook for each mailbox.
.AUTHOR
Shehryar Hassan
.EXAMPLE
.\Set-BulkCalendarPermission.ps1 -CsvPath .\calendar-permissions.csv
CSV columns expected: Mailbox, User, AccessRights
Example row: shared.sales@contoso.com, jane@contoso.com, Editor
#>
param(
[Parameter(Mandatory = $true)]
[string]$CsvPath,
[switch]$WhatIfOnly
)
if (-not (Get-Module -ListAvailable -Name ExchangeOnlineManagement)) {
Write-Error "The ExchangeOnlineManagement module is not installed. Run: Install-Module ExchangeOnlineManagement"
return
}
Import-Module ExchangeOnlineManagement
if (-not (Get-ConnectionInformation)) {
Connect-ExchangeOnline
}
if (-not (Test-Path $CsvPath)) {
Write-Error "CSV file not found at $CsvPath"
return
}
$rows = Import-Csv -Path $CsvPath
if (-not $rows -or $rows.Count -eq 0) {
Write-Error "No rows found in $CsvPath. Expected columns: Mailbox, User, AccessRights"
return
}
$validRights = @(
"Owner", "PublishingEditor", "Editor", "PublishingAuthor", "Author",
"NonEditingAuthor", "Reviewer", "Contributor", "AvailabilityOnly", "LimitedDetails"
)
$results = @()
foreach ($row in $rows) {
$mailbox = $row.Mailbox
$user = $row.User
$rights = $row.AccessRights
if ([string]::IsNullOrWhiteSpace($mailbox) -or [string]::IsNullOrWhiteSpace($user) -or [string]::IsNullOrWhiteSpace($rights)) {
Write-Warning "Skipping row with missing values: $($row | Out-String)"
continue
}
if ($validRights -notcontains $rights) {
Write-Warning "Skipping $mailbox, unrecognized AccessRights value: $rights"
continue
}
$folder = "$($mailbox):\Calendar"
$status = "Unknown"
try {
$existing = Get-MailboxFolderPermission -Identity $folder -User $user -ErrorAction SilentlyContinue
if ($WhatIfOnly) {
$status = if ($existing) { "Would update to $rights" } else { "Would add with $rights" }
}
elseif ($existing) {
Set-MailboxFolderPermission -Identity $folder -User $user -AccessRights $rights -ErrorAction Stop
$status = "Updated to $rights"
}
else {
Add-MailboxFolderPermission -Identity $folder -User $user -AccessRights $rights -ErrorAction Stop
$status = "Added with $rights"
}
}
catch {
$status = "Failed: $($_.Exception.Message)"
}
$results += [pscustomobject]@{
Mailbox = $mailbox
User = $user
AccessRights = $rights
Result = $status
}
}
$results | Format-Table -AutoSize
$outputPath = Join-Path -Path (Split-Path $CsvPath -Parent) -ChildPath "calendar-permission-results.csv"
$results | Export-Csv -Path $outputPath -NoTypeInformation
Write-Host "Results saved to $outputPath"Read it before you run it, and test in a safe tenant first.