Repository navigation
Expand file tree
/
Copy pathPowerShell-Graph-DeleteAllEventsInTimeRange.ps1
More file actions
130 lines (101 loc) · 4.17 KB
/
Copy pathPowerShell-Graph-DeleteAllEventsInTimeRange.ps1
File metadata and controls
130 lines (101 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# PowerShell-Graph-DeleteAllEventsInTimeRange.ps1
#
# This script deletes all calendar events for a specified user within a given date range using Microsoft Graph API.
# Note: Use with caution. Always test in a non-production environment first.
#
# Prerequisites:
# - Azure AD App Registration with appropriate permissions (Calendars.ReadWrite)
# - PowerShell 7.x or later recommended for best compatibility with Graph API.
# Author: Your Name
# Date: 2026-05-01
# Usage:
# 1. Update the configuration section with your tenant, app registration details, user UPN
# and desired date range.
# 2. Run the script in PowerShell. It will acquire an access token, query for events in the specified date range, and delete them one by one.
# Note: Deletion is irreversible. Always ensure you have backups or have tested the script in a safe environment before running it against production data.
# ================================
# DISCLAIMER
# This script is provided "as is" without any warranties. The author is not responsible for any data loss or issues that may arise from using this script. Use at your own risk.
# Always test in a non-production environment first and ensure you have appropriate permissions and backups before running the script.
# ================================
# ================================
# CONFIGURATION
# ================================
$TenantId = "YOUR_TENANT_ID"
$ClientId = "YOUR_CLIENT_ID"
$ClientSecret = "YOUR_CLIENT_SECRET"
$UserUPN = "user@contoso.com"
# Date Range (UTC required for best results)
$StartDateTime = "2020-01-06T00:00:00Z" # UTC time
$EndDateTime = "2020-01-06T23:59:59Z" # UTC time
# ================================
# GET TOKEN (Client Credentials)
# ================================
$TokenBody = @{
client_id = $ClientId
client_secret = $ClientSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}
$TokenResponse = Invoke-RestMethod -Method Post `
-Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body $TokenBody
$AccessToken = $TokenResponse.access_token
Write-Host "Access token acquired."
# ================================
# BUILD AUTH HEADER
# ================================
$Headers = @{
"Authorization" = "Bearer $AccessToken"
"Content-Type" = "application/json"
}
# ================================
# GET EVENTS IN DATE RANGE
# ================================
$EventsUrl = "https://graph.microsoft.com/v1.0/users/$UserUPN/calendarView" +
"?startDateTime=$StartDateTime&endDateTime=$EndDateTime"
Write-Host "Querying events for $($UserUPN) beteen $($StartDateTime) and $($EndDateTime)..."
$AllEvents = @()
do {
$Response = Invoke-RestMethod -Method Get -Uri $EventsUrl -Headers $Headers
if ($Response.value) {
$AllEvents += $Response.value
}
$EventsUrl = $Response.'@odata.nextLink'
} while ($EventsUrl)
$total = $AllEvents.Count
Write-Host "Total events found: $total"
# ================================
# DELETE EVENTS
# ================================
$i = 0
$lastReportedPercent = -1
Write-Host "Deleting events..."
foreach ($Event in $AllEvents) {
$i++
$EventId = $Event.id
$Subject = $Event.subject
$DeleteUrl = "https://graph.microsoft.com/v1.0/users/$UserUPN/events/$EventId"
try {
$DeleteResponse = Invoke-WebRequest -Method Delete `
-Uri $DeleteUrl `
-Headers $Headers `
-ErrorAction Stop
#Write-Host "Deleted: $Subject | ID: $EventId | Status: $($DeleteResponse.StatusCode)"
# 204 - No content is expected on successful delete
}
catch {
Write-Host "FAILED: $Subject | ID: $EventId"
Write-Host "StatusCode: $($_.Exception.Response.StatusCode.value__)"
Write-Host "Error: $($_.ErrorDetails.Message)"
}
# Check if progress reached a 10% increment
$percent = [int](($i + 1) / $total * 100)
# Only display at 10% increments
if ($percent % 10 -eq 0 -and $percent -ne $lastReportedPercent) {
Write-Host "$percent% completed"
$lastReportedPercent = $percent
}
}
Write-Host "Done."