Tuesday, September 8, 2026

Microsoft 365 — Granting One User Access to Another User's Calendar

Microsoft 365 — Granting One User Access to Another User's Calendar

A complete reference: PowerShell commands, UI paths, end-user guidance, troubleshooting, and auditing.

Throughout this guide:

PlaceholderMeaning
user2@contoso.comThe calendar owner — the mailbox being shared
user1@contoso.comThe delegate — the person receiving access

1. Prerequisites

RequirementDetail
ModuleExchangeOnlineManagement (v3.x or later)
Admin roleExchange Administrator, or a custom role with Mail Recipients + Mailbox Folder Permissions entries
LicensingBoth mailboxes must be licensed Exchange Online mailboxes
MFASupported natively by Connect-ExchangeOnline
Install-Module ExchangeOnlineManagement -Scope CurrentUser   # one-time
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com

2. Core commands

$Owner    = "user2@contoso.com"    # calendar owner
$Delegate = "user1@contoso.com"    # who gets access

# 1. Check existing permissions
Get-MailboxFolderPermission -Identity "$($Owner):\Calendar"

# 2. Grant access
Add-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User $Delegate -AccessRights Editor

# 3. Change an existing entry (Add- fails if the user is already listed)
Set-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User $Delegate -AccessRights Reviewer

# 4. Remove access
Remove-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User $Delegate -Confirm:$false

The colon-backslash syntax (mailbox:\Folder) is required. $($Owner):\Calendar uses a subexpression because PowerShell would otherwise treat $Owner: as a scope qualifier.


3. Access rights reference

RightWhat the delegate can do
NoneNo access (explicit deny entry)
AvailabilityOnlyFree/busy only — the tenant default for Default
LimitedDetailsFree/busy + subject + location
ReviewerRead all item details
ContributorCreate items; cannot read existing ones
NonEditingAuthorRead all; delete own items only
AuthorRead, create, edit/delete own items
PublishingAuthorAuthor + create subfolders
EditorRead, create, edit/delete all items
PublishingEditorEditor + create subfolders
OwnerFull control, including changing permissions

Editor is the usual choice for an assistant managing someone's calendar. Reviewer is the usual choice for visibility-only.


4. True delegate access

Folder permissions alone do not make someone a delegate. A delegate additionally receives meeting invitations and can respond on the owner's behalf.

# Delegate flag on the calendar folder
Add-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User $Delegate `
    -AccessRights Editor -SharingPermissionFlags Delegate

# Delegate + can see private items
Set-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User $Delegate `
    -AccessRights Editor -SharingPermissionFlags Delegate,CanViewPrivateItems

# Send on behalf of the owner
Set-Mailbox -Identity $Owner -GrantSendOnBehalfTo @{Add=$Delegate}

# Route meeting invites to the delegate
Set-CalendarProcessing -Identity $Owner -ResourceDelegates $Delegate

# Full mailbox access (only if the whole mailbox is needed, not just the calendar)
Add-MailboxPermission -Identity $Owner -User $Delegate -AccessRights FullAccess -InheritanceType All

Notes:

  • -SharingPermissionFlags is only valid when -AccessRights is Editor.
  • CanViewPrivateItems cannot be set without Delegate.
  • Use @{Add=...} / @{Remove=...} on GrantSendOnBehalfTo — assigning directly overwrites every existing entry.

Send on Behalf vs Send As

Appears asCommand
Send on Behalfuser1 on behalf of user2Set-Mailbox -GrantSendOnBehalfTo
Send Asuser2 (no trace of user1)Add-RecipientPermission -AccessRights SendAs

Send As is stronger and generally reserved for shared mailboxes rather than personal ones.


5. The Default and Anonymous entries

Every calendar has two built-in principals that are easy to overlook:

Get-MailboxFolderPermission -Identity "$($Owner):\Calendar" |
    Where-Object { $_.User -match "Default|Anonymous" }

# Let everyone in the organisation see subject and location
Set-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User Default -AccessRights LimitedDetails

# Ensure external/anonymous users have nothing
Set-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User Anonymous -AccessRights None

Raising Default is often a better answer than granting dozens of individual permissions. Set the org-wide baseline for new mailboxes with:

Get-OrganizationConfig | Select-Object DefaultAuthenticationPolicy, ACLableSyncedObjectEnabled
Set-MailboxFolderPermission -Identity "$($Owner):\Calendar" -User Default -AccessRights AvailabilityOnly

There is no supported tenant switch that changes the default for future mailboxes, so this is normally handled by a scheduled script over new users.


6. Non-English mailboxes

The folder is named Kalender, Calendrier, カレンダー and so on depending on the mailbox language, so a hard-coded :\Calendar fails. Resolve the name dynamically:

$CalFolder = (Get-MailboxFolderStatistics -Identity $Owner -FolderScope Calendar |
              Where-Object { $_.FolderType -eq "Calendar" }).Name

Add-MailboxFolderPermission -Identity "$($Owner):\$CalFolder" -User $Delegate -AccessRights Editor

This is the single most common cause of "the mailbox folder cannot be found" errors in multinational tenants.


7. Bulk operations

Grant from CSV

CSV with columns Owner,Delegate,Rights:

Import-Csv .\CalendarAccess.csv | ForEach-Object {
    $id = "$($_.Owner):\Calendar"
    $existing = Get-MailboxFolderPermission -Identity $id -User $_.Delegate -ErrorAction SilentlyContinue
    if ($existing) {
        Set-MailboxFolderPermission -Identity $id -User $_.Delegate -AccessRights $_.Rights
    } else {
        Add-MailboxFolderPermission -Identity $id -User $_.Delegate -AccessRights $_.Rights
    }
}

Idempotent helper function

function Set-CalendarAccess {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Owner,
        [Parameter(Mandatory)][string]$Delegate,
        [ValidateSet('AvailabilityOnly','LimitedDetails','Reviewer','Contributor',
                     'NonEditingAuthor','Author','PublishingAuthor','Editor',
                     'PublishingEditor','Owner','None')]
        [string]$Rights = 'Reviewer',
        [switch]$AsDelegate
    )

    $folder = (Get-MailboxFolderStatistics -Identity $Owner -FolderScope Calendar |
               Where-Object { $_.FolderType -eq 'Calendar' }).Name
    $id = "$($Owner):\$folder"

    $params = @{ Identity = $id; User = $Delegate; AccessRights = $Rights }
    if ($AsDelegate -and $Rights -eq 'Editor') { $params.SharingPermissionFlags = 'Delegate' }

    $current = Get-MailboxFolderPermission -Identity $id -User $Delegate -ErrorAction SilentlyContinue
    if ($current) {
        Set-MailboxFolderPermission @params
        Write-Host "Updated $Delegate -> $Owner ($Rights)" -ForegroundColor Yellow
    } else {
        Add-MailboxFolderPermission @params
        Write-Host "Granted $Delegate -> $Owner ($Rights)" -ForegroundColor Green
    }
}

# Usage
Set-CalendarAccess -Owner "user2@contoso.com" -Delegate "user1@contoso.com" -Rights Editor -AsDelegate

Tenant-wide audit report

$report = foreach ($mbx in Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox) {
    $folder = (Get-MailboxFolderStatistics -Identity $mbx.UserPrincipalName -FolderScope Calendar |
               Where-Object { $_.FolderType -eq 'Calendar' }).Name
    Get-MailboxFolderPermission -Identity "$($mbx.UserPrincipalName):\$folder" -ErrorAction SilentlyContinue |
        Where-Object { $_.User.DisplayName -notin @('Default','Anonymous') } |
        Select-Object @{N='Owner';E={$mbx.UserPrincipalName}},
                      @{N='Delegate';E={$_.User.DisplayName}},
                      @{N='Rights';E={$_.AccessRights -join ','}},
                      @{N='Flags';E={$_.SharingPermissionFlags}}
}
$report | Export-Csv .\CalendarPermissionReport.csv -NoTypeInformation

Run this against a subset first — a full tenant scan makes two calls per mailbox and is slow on large directories.

Offboarding cleanup

When someone leaves, their entries persist on every calendar they had access to. Find and clear them:

$LeaverUpn = "user1@contoso.com"

foreach ($mbx in Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox) {
    $id = "$($mbx.UserPrincipalName):\Calendar"
    if (Get-MailboxFolderPermission -Identity $id -User $LeaverUpn -ErrorAction SilentlyContinue) {
        Remove-MailboxFolderPermission -Identity $id -User $LeaverUpn -Confirm:$false
        Write-Host "Removed from $($mbx.UserPrincipalName)"
    }
}

8. Room and resource mailboxes

Resource calendars behave differently — booking is controlled by Set-CalendarProcessing, not folder rights.

Get-CalendarProcessing -Identity "room1@contoso.com" | Format-List

Set-CalendarProcessing -Identity "room1@contoso.com" `
    -AutomateProcessing AutoAccept `
    -AllBookInPolicy $false `
    -BookInPolicy "team-group@contoso.com" `
    -ResourceDelegates "user1@contoso.com" `
    -AddOrganizerToSubject $true `
    -DeleteSubject $false

Set -AutomateProcessing AutoUpdate when a human delegate should approve every request instead of auto-accepting.


9. External / cross-tenant calendar sharing

Sharing with someone outside the tenant is governed by a sharing policy, not by folder permissions.

Get-SharingPolicy | Format-List Name, Domains, Enabled, Default

# Allow free/busy with a specific partner domain
Set-SharingPolicy -Identity "Default Sharing Policy" `
    -Domains "Anonymous:CalendarSharingFreeBusySimple",
             "partner.com:CalendarSharingFreeBusyReviewer"

Domain-level values: CalendarSharingFreeBusySimple, CalendarSharingFreeBusyDetail, CalendarSharingFreeBusyReviewer, ContactsSharing.

For richer cross-tenant free/busy, Organization Relationships (New-OrganizationRelationship) or B2B direct connect are the appropriate mechanisms.


10. Where each permission is visible in the UI

Permission typeIn Exchange admin center?Where to actually check
Calendar folder rights (Reviewer, Editor…)NoOwner's Outlook, or PowerShell
Delegate flag / invite forwardingNoOwner's Outlook → Delegate Access
Send on behalfYesEAC → Recipients → Mailboxes → owner → Delegation
Full Access / Send AsYesEAC → Recipients → Mailboxes → owner → Delegation

The most common gap: calendar-level sharing is a mailbox folder property, so it does not appear anywhere in the Microsoft 365 admin center. Get-MailboxFolderPermission remains the only reliable admin-side check.

Checking in EAC

  1. Go to admin.exchange.microsoft.comRecipients → Mailboxes
  2. Select the owner → Delegation tab
  3. Review Read and manage, Send as, Send on behalf

11. Owner-side UI steps (granting access)

New Outlook / Outlook on the web Calendar → hover My Calendars → CalendarSharing and permissions → enter the delegate → choose a permission level → Share.

Classic Outlook Calendar → right-click CalendarProperties → Permissions tab → Add → select the delegate → set the level → OK.

Delegate access (accepts invites on the owner's behalf) Classic Outlook → File → Account Settings → Delegate Access → Add → set Calendar to Editor → tick Delegate receives copies of meeting-related messages.

Outlook mobile Calendar sharing cannot be granted from mobile; only viewing already-shared calendars is supported.


12. Delegate-side UI steps (opening the calendar)

ClientSteps
New Outlook / OWACalendar → Add calendar → Add from directory → select own account → type the owner → choose Other calendarsAdd
Classic OutlookCalendar → Add Calendar → Open Shared Calendar → type the owner → OK
Outlook mobileCalendar → menu → Add calendar → Add shared calendars → search the owner

Important: when access is granted via PowerShell, no sharing invitation email is sent. The delegate must add the calendar manually. This is the step most people get stuck on.

Ready-to-send note for the delegate

Access to [Owner]'s calendar has been granted. Nothing will arrive in your inbox, so please add it manually: in Outlook go to Calendar → Add Calendar → Open Shared Calendar, type the owner's address, and select OK. In the web or new Outlook, use Add calendar → Add from directory. It can take up to an hour to appear; if it does not, restart Outlook once.


13. Verification

Get-MailboxFolderPermission -Identity "user2@contoso.com:\Calendar" |
    Format-Table User, AccessRights, SharingPermissionFlags -AutoSize

SharingPermissionFlags showing Delegate confirms true delegate status rather than plain folder sharing.

Also worth checking:

# Who can send on behalf
Get-Mailbox -Identity $Owner | Select-Object -ExpandProperty GrantSendOnBehalfTo

# Full mailbox access
Get-MailboxPermission -Identity $Owner | Where-Object { $_.User -notlike "NT AUTHORITY\*" }

# Send As
Get-RecipientPermission -Identity $Owner | Where-Object { $_.Trustee -notlike "NT AUTHORITY\*" }

14. Troubleshooting

Symptom / errorCauseFix
The mailbox folder cannot be foundLocalised folder name, or unlicensed/uninitialised mailboxResolve the folder name via Get-MailboxFolderStatistics (section 6)
An existing permission entry was found for userEntry already existsUse Set-MailboxFolderPermission instead of Add-
There is no existing permission entry found for userNo entry to modifyUse Add-MailboxFolderPermission first
Couldn't find object … please make sure you've typed it correctlyMail contact or unlicensed accountConfirm with Get-Recipient
Access granted but calendar not visibleCached mode / OST not refreshedRestart Outlook; allow up to 60 minutes; test in OWA first to isolate
Delegate sees free/busy onlyPermission applied to the wrong folder or Default overrides expectationRe-run Get-MailboxFolderPermission and confirm the named entry
Private items hiddenCanViewPrivateItems not setRe-apply with -SharingPermissionFlags Delegate,CanViewPrivateItems
Delegate not receiving invitesFolder permission set but no delegate flagAdd -SharingPermissionFlags Delegate and set ResourceDelegates
Permission reverts after a whileA competing script or sharing policy is resetting itCheck the audit log (below)

Audit who changed a permission

Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
    -Operations "Add-MailboxFolderPermission","Set-MailboxFolderPermission","Remove-MailboxFolderPermission" `
    -ResultSize 500 | Select-Object CreationDate, UserIds, Operations, AuditData

Requires unified auditing to be enabled (Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled).


15. Microsoft Graph alternative

Graph is the better fit for app-only automation, Azure Functions, or Logic Apps where an interactive Exchange session is impractical.

POST https://graph.microsoft.com/v1.0/users/{owner-id}/calendar/calendarPermissions
Content-Type: application/json

{
  "isRemovable": true,
  "isInsideOrganization": true,
  "role": "write",
  "emailAddress": {
    "address": "user1@contoso.com",
    "name": "User One"
  }
}
Graph roleEquivalent Exchange right
freeBusyReadAvailabilityOnly
limitedReadLimitedDetails
readReviewer
writeEditor
delegateWithoutPrivateEventAccessEditor + Delegate
delegateWithPrivateEventAccessEditor + Delegate + CanViewPrivateItems
customRead-only value; cannot be assigned

Required permission: Calendars.ReadWrite (delegated) or Calendars.ReadWrite (application, ideally scoped with an application access policy).

Graph does not expose Send on Behalf or Full Access — those remain Exchange PowerShell operations.


16. Cleanup

Disconnect-ExchangeOnline -Confirm:$false

Always disconnect in scripted or runbook contexts; unclosed sessions count toward the concurrent connection limit.


Quick decision guide

RequirementWhat to configure
See if someone is busyDefault = AvailabilityOnly (usually already set)
See subjects across the orgDefault = LimitedDetails
Read one person's full calendarReviewer for that user
Manage a manager's calendarEditor + -SharingPermissionFlags Delegate + GrantSendOnBehalfTo
Also handle private appointmentsAdd CanViewPrivateItems
Manage a meeting roomSet-CalendarProcessing with ResourceDelegates
Share with an external partnerSharing policy or organization relationship
Access the whole mailboxAdd-MailboxPermission -AccessRights FullAccess

No comments:

Post a Comment

Featured Post

Nexthink Infinity — Complete Study Guide

Nexthink Infinity — Complete Study Guide A self-contained learning resource covering every topic in the Nexthink Infinity curriculum: DEX fo...

Popular posts