Skip to content

Instantly share code, notes, and snippets.

@bill-long
Last active March 8, 2024 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bill-long/d8c080ce21e2a8fcd47e99db70cfba9e to your computer and use it in GitHub Desktop.
Save bill-long/d8c080ce21e2a8fcd47e99db70cfba9e to your computer and use it in GitHub Desktop.
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "High")]
param (
[Parameter(Mandatory)]
[string]
$Server,
[Parameter(Mandatory)]
[string]
$Mailbox,
[Parameter(Mandatory)]
[bool]
$RepairBadItems,
[Parameter()]
[string]
$EWSModulePath = (Join-Path ((Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\v15\Setup).MsiInstallPath) "bin\Microsoft.Exchange.WebServices.dll"),
[Parameter()]
[System.Management.Automation.PSCredential]
$Credentials
)
Import-Module $EWSModulePath
$exchService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
if ($null -eq $Credentials) {
$exchService.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
} else {
$exchService.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Credentials.UserName, [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credentials.Password)))
}
$exchService.Url = New-Object Uri("https://$Server/EWS/Exchange.asmx")
$mbx = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($Mailbox)
$calendarId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar, $mbx)
$arrayOfPropertiesToLoad = @(
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::End,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::EndTimeZone,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::IsAllDayEvent,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::IsOnlineMeeting,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Location,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::MyResponseType,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Organizer,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Start,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::StartTimeZone,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::AppointmentType,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::IsResponseRequested,
[Microsoft.Exchange.WebServices.Data.ItemSchema]::IsReminderSet,
[Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject,
[Microsoft.Exchange.WebServices.Data.ItemSchema]::Sensitivity,
[Microsoft.Exchange.WebServices.Data.ItemSchema]::LastModifiedTime
)
$propertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet($arrayOfPropertiesToLoad)
$calendarView = New-Object Microsoft.Exchange.WebServices.Data.CalendarView([DateTime]::Now.AddMonths(-6), [DateTime]::Now, 1000)
$calendarView.PropertySet = $propertySet
$appointments = $exchService.FindAppointments($calendarId, $calendarView)
Write-Host "Retrieved $($appointments.Items.Count) appointments."
if ($null -eq (Get-TypeData "CSSExchange.TestCalendarEWSResult")) {
Update-TypeData -TypeName "CSSExchange.TestCalendarEWSResult" -DefaultDisplayPropertySet "LastModifiedTime", "IsAllDayEvent", "Subject"
}
$badItems = @()
foreach ($appt in $appointments) {
$apptProps = @{
UniqueId = $appt.Id.UniqueId
LastModifiedTime = $appt.LastModifiedTime
Subject = $appt.Subject
}
try {
$apptProps['IsAllDayEvent'] = $appt.IsAllDayEvent
} catch {
Write-Warning "Exception thrown while retrieving IsAllDayEvent property for appointment $($appt.Id.UniqueId): $_"
$apptProps['IsAllDayEvent'] = $_.ToString()
}
$isBadItem = ($apptProps['IsAllDayEvent'] -ne $true -and $apptProps['IsAllDayEvent'] -ne $false)
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -or $isBadItem) {
$outputObj = [PSCustomObject]$apptProps
$outputObj.PSObject.TypeNames.Insert(0, 'CSSExchange.TestCalendarEWSResult')
$outputObj
}
if ($isBadItem) {
$badItems += $appt
}
}
if ($RepairBadItems -and $badItems.Count -gt 0) {
Write-Host "Attempting to fix bad items..."
foreach ($badItem in $badItems) {
if ($PSCmdlet.ShouldProcess("Fixing item: $($badItem.Subject)", "Fix item")) {
try {
$badItem.IsAllDayEvent = $false
$badItem.Update("AutoResolve", $true)
Write-Host "Fixed item: $($badItem.Subject)"
} catch {
Write-Host "Failed to fix item: $($badItem.Subject) due to error: $_"
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment