We regularly get requests for an automated way of deleting duplicate appointments from calendars (most often caused by migration issues or mistaken mailbox imports, but there are lots of reasons that you could end up with duplicates). So, here is a script that checks for and deletes duplicates. As usual, it uses EWS to connect to the mailbox, and requires the EWS Managed API to work (and does not need to be run on the Exchange server - any client machine will do).
A calendar item is considered a duplicate if either of these conditions is true:
- The iCALUID of the item matches the iCALUID of another item. Calendar items should be unique - if a matching uid is found, no further check is made and the matched appointment is deleted.
- The subject, start, and end time match another item.
The script works by first of all reading all the appointments, and then checking each and building up a list of any duplicates. Once all the items have been checked, the duplicate items are deleted in bulk (in batches of 500). Currently the script will only work for appointments, though you can use it against public folder calendars or any other as needed (by using -FolderPath and -PublicFolders parameters as necessary).
To run it against a single mailbox using the credentials of the logged in user:
.\Remove-DuplicateAppointments.ps1 -mailbox email@example.com
To run it using alternative credentials (you'll be prompted for the credentials):
.\Remove-DuplicateAppointments.ps1 -mailbox firstname.lastname@example.org -Credentials (Get-Credential)
Other useful parameters (there are more, but check the script for further information):
-FolderPath: use to specify the path of the calendar to be processed (only use if not the default calendar, e.g. "\Calendar2")
-PublicFolders: this switch needs to be specified if the folder path points to a calendar in public folders (otherwise the path is relative to the mailbox)
-WhatIf: if this switch is present, no changes are made, but items that would be deleted are logged
-LogFile: information is written to this file showing what has been deleted (or would be deleted if -WhatIf is also present)