ExportImport-CalendarProcessing.ps1
<#PSScriptInfo
.VERSION 5.1 .GUID d77c0c5e-1b8a-4bfe-91bc-02f68ed8a85c .AUTHOR Aaron Guilmette .COMPANYNAME Microsoft .COPYRIGHT 2020 .TAGS .LICENSEURI .PROJECTURI https://www.undocumented-features.com/2017/01/19/export-and-import-calendar-processing-information/ .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .DESCRIPTION Export/Import Resource Booking Parameters. .PRIVATEDATA #> <# .SYNOPSIS Export/Import resource booking parameters for migrating resource mailbox calendar processing information. In many instances, calendar processing configuration is not persisted during mailbox migrations, so it is advisable to export it prior to resource mailbox migration. .PARAMETER Credential Specify the credential used for the import or export action. .PARAMETER Domains Filter export results based on domain. .PARAMETER Export Enable export mode. .PARAMETER ExportFile Specify the file to export resource booking data to. .PARAMETER ExportUri Specify the endpoint for export. .PARAMETER Identity Specify an individual identity for import or export. .PARAMETER Import Enable import mode. .PARAMETER ImportFile Specify the file to use containing resource booking data. .PARAMETER ImportUri Specify the endpoint for import. .PARAMETER UseExistingSession Use the existing Exchange or Exchange Online session. .EXAMPLE .\ExportImport-CalendarProcessing.ps1 -Export -Credential (Get-Credential) -ExportFile CalendarProcessingData.csv Connects to Office 365 using credential specified in (Get-Credential) and exports calendar processing data for resource mailboxes to CalendarProcessingData.csv. .EXAMPLE .\ExportImport-CalendarProcessing.ps1 -Export -ExportUri https://onpremexchangeserver/powershell -UseExistingCredential -ExportFile CalendarProcessingData.csv Connects to on-premises Exchange Server "onpremexchangeserver" using the currently logged-in credential and exports calendar processing data for resource mailboxes to CalendarProcessingData.csv. .LINK https://www.undocumented-features.com/2017/01/19/export-and-import-calendar-processing-information/ .NOTES 2020-04-21 Updated for PowerShell Gallery. 2019-03-11 Updated to remove Append parameter from Export-Csv. 2018-10-05 Updated to wrap resource delegates, requestoutofpolicy, requestinpolicy, bookinpolicy attribute values in quotes. 2018-05-16 Updated Identity parameter to support an array input. 2018-04-05 Fixed typo in AllRequestOutOfPolicy. Added .Description to comment-based help. Added .Example to comment-based help. #> [CmdletBinding()] param ( # Export Parameters [parameter(Mandatory=$false,ParameterSetName = "Export")] [ValidateNotNullOrEmpty()] [Switch]$Export, [String]$ExportUri = "https://outlook.office365.com/powershell-liveid/", [Array]$Domains, [parameter(Mandatory=$true,ParameterSetName = "Export")] [string]$ExportFile, # Import Parameters [parameter(Mandatory=$false,ParameterSetName = "Import")] [ValidateNotNullOrEmpty()] [Switch]$Import, [String]$ImportUri = "https://outlook.office365.com/powershell-liveid/", [parameter(Mandatory=$true,ParameterSetName = "Import")] [String]$ImportFile, # Global Parameters [parameter(Mandatory=$false,ParameterSetName = "Export")] [parameter(ParameterSetName = "Import")] [System.Management.Automation.CredentialAttribute()]$Credential, [array]$Identity, [string]$LogFile = ".\CalendarExportImport.csv", [switch]$UseExistingSession ) Function o365LogonExport { $ExportSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ExportUri -Credential $Credential -Authentication Basic -AllowRedirection Import-PSSession $ExportSession } Function o365LogonImport { $ImportSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ImportUri -Credential $Credential -Authentication Basic -AllowRedirection Import-PSSession $ImportSession } Switch($PSCmdlet.ParameterSetName) { Export { # Connect to source Exchange environment If (!($UseExistingSession)) { o365LogonExport } # Create the domain filter If ($Domains) { $DomainsCount = $Domains.Count $i = 1 $Filter = "{WindowsEmailAddress -like " Foreach ($Domain in $Domains) { If ($Domain.StartsWith("*")) { # Value already starts with an asterisk } Else { $Domain = "*" + $Domain } #$Filter = [scriptblock]::Create("{WindowsEmailAddress -like `"$Domain`"}") #$Filter = [scriptblock]::Create("`"$Domain`"") $Filter = $Filter + "`"$Domain`" -or WindowsEmailAddress -like " } $Filter = $Filter.Substring(0, $Filter.Length - 30) $Filter = $Filter + "}" Write-Host -NoNewline "Domain Filter is "; Write-Host -ForegroundColor Green $Filter } # Get the user list If ($Identity) { $Resources = @() foreach ($obj in $Identity) { [array]$Resources += (Get-Mailbox $obj) } } Else { Write-Host -ForegroundColor Green "Processing all mailboxes." #$cmd = "Get-Mailbox -ResultSize Unlimited -Filter { WindowsEmailAddress -like $Filter } -RecipientTypeDetails RoomMailbox,SharedMailbox,EquipmentMailbox" If ($Filter) { $cmd = "Get-Mailbox -ResultSize Unlimited -Filter $Filter -RecipientTypeDetails RoomMailbox,SharedMailbox,EquipmentMailbox" } Else { $cmd = "Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails RoomMailbox,SharedMailbox,EquipmentMailbox" } [array]$Resources = Invoke-Expression $cmd } Write-Host "Found $($Resources.Count) mailboxes." $Count = $Resources.Count $ResourceMailboxesSettings = @() $i = 1 Foreach ($obj in $Resources) { Write-Host "Processing [$i / $Count] - $($obj.PrimarySmtpAddress)" $ResourceMailboxSetting = Get-CalendarProcessing $obj.PrimarySmtpAddress.ToString() Add-Member -InputObject $ResourceMailboxSetting -MemberType NoteProperty -Name "PrimarySmtpAddress" -Value $obj.PrimarySmtpAddress $ResourceMailboxesSettings += $ResourceMailboxSetting $i++ } Write-Host "Making it pretty...please wait." $ResourceMailboxesSettings | Select PrimarySmtpAddress,` AutomateProcessing,` AllowConflicts,` BookingWindowInDays,` MaximumDurationInMinutes,` AllowRecurringMeetings,` EnforceSchedulingHorizon,` ScheduleOnlyDuringWorkHours,` ConflictPercentageAllowed,` MaximumConflictInstances,` ForwardRequestsToDelegates,` DeleteAttachments,` DeleteComments,` RemovePrivateProperty,` DeleteSubject,` AddOrganizerToSubject,` DeleteNonCalendarItems,` TentativePendingApproval,` EnableResponseDetails,` OrganizerInfo,` @{ n = 'ResourceDelegates'; e = { $val1 = @(); foreach ($obj in $_.ResourceDelegates) { $val1 += (Get-Recipient $obj).PrimarySmtpAddress }; $val1 = """" + ($val1 -join '";"') + """"; $val1 } },` @{ n = 'RequestOutOfPolicy'; e = { $val2 = @(); foreach ($obj in $_.RequestOutOfPolicy) { $val2 += (Get-Recipient $obj).PrimarySmtpAddress }; $val2 = """" + ($val2 -join '";"') + """"; $val2 } },` @{ n = 'BookInPolicy'; e = { $val3 = @(); foreach ($obj in $_.BookInPolicy) { $val3 += (Get-Recipient $obj).PrimarySmtpAddress }; $val3 = """" + ($val3 -join '";"') + """"; $val3 } },` @{ n = 'RequestInPolicy'; e = { $val4 = @(); foreach ($obj in $_.RequestInPolicy) { $val4 += (Get-Recipient $obj).PrimarySmtpAddress }; $val4 = """" + ($val4 -join '";"') + """"; $val4 } },` #@{n='ResourceDelegates';e={$val1=@();foreach ($obj in $_.ResourceDelegates){ $val1 += (Get-Recipient $obj).PrimarySmtpAddress} $val1 -join ";"}},` #@{n="RequestOutOfPolicy";e={$val2=@();foreach ($obj in $_.RequestOutOfPolicy){ $val2 += (Get-Recipient $obj).PrimarySmtpAddress} $val2 -join ";"}},` #@{n="RequestInPolicy";e={$val4=@();foreach ($obj in $_.RequestInPolicy){ $val4 += (Get-Recipient $obj).PrimarySmtpAddress} $val4 -join ";"}},` #@{n="BookInPolicy";e={$val3=@();foreach ($obj in $_.BookInPolicy){ $val3 += (Get-Recipient $obj).PrimarySmtpAddress} $val3 -join ";"}},` AllRequestOutOfPolicy,` AllBookInPolicy,` AllRequestInPolicy,` AddAdditionalResponse,` AdditionalResponse,` RemoveOldMeetingMessages,` AddNewRequestsTentatively,` ProcessExternalMeetingMessages,` RemoveForwardedMeetingNotifications ` | Export-Csv -NoTypeInformation $ExportFile # -Append Write-Host -NoNewline "Export file is "; Write-Host -NoNewLine -ForegroundColor Green $ExportFile; Write-Host "." Get-PSSession | ? { $_.ConfigurationName -eq "Microsoft.Exchange" } | Remove-PSSession } # End Export Import { # Connect to target Exchange environment If (!($UseExistingSession)) { o365LogonImport } If ($Identity) { $Temp = Import-Csv $ImportFile [array]$ResourceMailboxSettings = $Temp | ? { $_.PrimarySmtpAddress -match $Identity } } Else { [array]$ResourceMailboxSettings = Import-Csv $ImportFile } $i = 1 $Count = $ResourceMailboxSettings.Count Write-Host "Processing $($Count) mailboxes." Foreach ($Mailbox in $ResourceMailboxSettings) { Write-Host "Processing [$i / $Count] - $($Mailbox.PrimarySmtpAddress)" $RecipientType = (Get-Mailbox $Mailbox.PrimarySmtpAddress).RecipientTypeDetails $cmd = "Set-CalendarProcessing -Identity $($Mailbox.PrimarySmtpAddress)" If ($Mailbox.AutomateProcesing) { $AutomateProcessing = $Mailbox.AutomateProcessing; $cmd = $cmd + " -AutomateProcessing $AutomateProcessing" } If ($Mailbox.AllowConflicts) { $AllowConflicts = "`$"+$Mailbox.AllowConflicts; $cmd = $cmd + " -AllowConflicts $AllowConflicts" } If ($Mailbox.BookingWindowInDays) { $BookingWindowInDays = $Mailbox.BookingWindowInDays; $cmd = $cmd + " -BookingWindowInDays $BookingWindowInDays" } If ($Mailbox.MaximumDurationInMinutes) { $MaximumDurationInMinutes = $Mailbox.MaximumDurationInMinutes; $cmd = $cmd + " -MaximumDurationInMinutes $MaximumDurationInMinutes" } If ($Mailbox.AllowRecurringMeetings) { $AllowRecurringMeetings = "`$"+$Mailbox.AllowRecurringMeetings; $cmd = $cmd + " -AllowRecurringMeetings $AllowRecurringMeetings" } If ($Mailbox.EnforceSchedulingHorizon) { $EnforceSchedulingHorizon = "`$"+$Mailbox.EnforceSchedulingHorizon; $cmd = $cmd + " -EnforceSchedulingHorizon $EnforceSchedulingHorizon" } If ($Mailbox.ScheduleOnlyDuringWorkingHours) { $ScheduleOnlyDuringWorkingHours = "`$"+$Mailbox.ScheduleOnlyDuringWorkingHours; $cmd = $cmd + " -ScheduleOnlyDuringWorkingHours $ScheduleOnlyDuringWorkingHours" } If ($Mailbox.ConflictPercentageAllowed) { $ConflictPercentageAllowed = $Mailbox.ConflictPercentageAllowed; $cmd = $cmd + " -ConflictPercentageAllowed $ConflictPercentageAllowed" } If ($Mailbox.MaximumConflictInstances) { $MaximumConflictInstances = $Mailbox.MaximumConflictInstances; $cmd = $cmd + " -MaximumConflictInstances $MaximumConflictInstances" } If ($Mailbox.ForwardRequestsToDelegate) { $ForwardRequestsToDelegate = "`$"+$Mailbox.ForwardRequestsToDelegate; $cmd = $cmd + " -ForwardRequestsToDelegate $ForwardRequestsToDelegate" } If ($Mailbox.DeleteAttachments) { $DeleteAttachments = "`$"+$Mailbox.DeleteAttachments; $cmd = $cmd + " -DeleteAttachments $DeleteAttachments" } If ($Mailbox.DeleteComments) { $DeleteComments = "`$"+$Mailbox.DeleteComments; $cmd = $cmd + " -DeleteComments $DeleteComments" } If ($Mailbox.RemovePrivateProperty) { $RemovePrivateProperty = "`$"+$Mailbox.RemovePrivateProperty; $cmd = $cmd + " -RemovePrivateProperty $RemovePrivateProperty" } If ($Mailbox.DeleteSubject) { $DeleteSubject = "`$"+$Mailbox.DeleteSubject; $cmd = $cmd + " -DeleteSubject $DeleteSubject" } If ($Mailbox.AddOrganizerToSubject) { $AddOrganizerToSubject = "`$"+$Mailbox.AddOrganizerToSubject; $cmd = $cmd + " -AddOrganizerToSubject $AddOrganizerToSubject" } If ($Mailbox.DeleteNonCalendarItems) { $DeleteNonCalendarItems = "`$"+$Mailbox.DeleteNonCalendarItems; $cmd = $cmd + " -DeleteNonCalendarItems $DeleteNonCalendarItems" } If ($Mailbox.TentativePendingApproval) { $TentativePendingApproval = "`$"+$Mailbox.TentativePendingApproval; $cmd = $cmd + " -TentativePendingApproval $TentativePendingApproval" } If ($Mailbox.EnableResponseDetails) { $EnableResponseDetails = "`$"+$Mailbox.EnableResponseDetails; $cmd = $cmd + " -EnableResponseDetails $EnableResponseDetails" } If ($Mailbox.OrganizerInfo) { $OrganizerInfo = "`$"+$Mailbox.OrganizerInfo; $cmd = $cmd + " -OrganizerInfo $OrganizerInfo" } If ($Mailbox.RequestOutOfPolicy -and $Mailbox.RequestOutOfPolicy -notmatch '^\"\"$') { $RequestOutOfPolicy = $Mailbox.RequestOutOfPolicy.Replace(";",","); $cmd = $cmd + " -RequestOutOfPolicy $RequestOutOfPolicy" } If ($Mailbox.AllRequestOutOfPolicy) { $AllRequestOutOfPolicy = "`$"+$Mailbox.AllRequestOutOfPolicy; $cmd = $cmd + " -AllRequestOutOfPolicy $AllRequestOutOfPolicy" } If ($Mailbox.BookInPolicy -and $Mailbox.BookInPolicy -notmatch '^\"\"$') { $BookInPolicy = $Mailbox.BookInPolicy.Replace(";",",").Replace(",,",","); $cmd = $cmd + " -BookInPolicy $BookInPolicy" } If ($Mailbox.AllBookInPolicy) { $AllBookInPolicy = "`$"+$Mailbox.AllBookInPolicy; $cmd = $cmd + " -AllBookInPolicy $AllBookInPolicy" } If ($Mailbox.RequestInPolicy -and $Mailbox.RequestInPolicy -notmatch '^\"\"$') { $RequestInPolicy = $Mailbox.RequestInPolicy.Replace(";",","); $cmd = $cmd + " -RequestInPolicy $RequestInPolicy" } If ($Mailbox.AllRequestInPolicy) { $AllRequestInPolicy = "`$"+$Mailbox.AllRequestInPolicy; $cmd = $cmd + " -AllRequestInPolicy $AllRequestInPolicy" } If ($Mailbox.AddAdditionalResponse) { $AddAdditionalResponse = "`$"+$Mailbox.AddAdditionalResponse; $cmd = $cmd + " -AddAdditionalResponse $AddAdditionalResponse" } If ($Mailbox.AdditionalResponse) { #$AdditionalResponse = $Mailbox.AdditionalResponse.Replace("\","\\").Replace(".","\.").Replace("^","\^").Replace("$","\$").Replace("*","\*").Replace("+","\+").Replace("-","\-").Replace("?","\?").Replace("(","\(").Replace(")","\)").Replace("[","\[").Replace("]","\]").Replace("{","\{").Replace("}","\}").Replace("|","\|").Replace("<","\<").Replace(">","\>").Replace(":","\:").Replace("@","\@").Replace("/","\/").Replace("'","\'") $AdditionalResponse = $Mailbox.AdditionalResponse $cmd = $cmd + " -AdditionalResponse ""$AdditionalResponse"" " } If ($Mailbox.RemoveOldMeetingMessages) { $RemoveOldMeetingMessages = "`$"+$Mailbox.RemoveOldMeetingMessages; $cmd = $cmd + " -RemoveOldMeetingMessages $RemoveOldMeetingMessages" } If ($Mailbox.RemoveForwardedMeetingNotifications) { $RemoveForwardedMeetingNotifications = "`$"+$Mailbox.RemoveForwardedMeetingNotifications; $cmd = $cmd + " -RemoveForwardedMeetingNotifications $RemoveForwardedMeetingNotifications" } # Params that fail if mailbox is not configured as "RoomMailbox" or "EquipmentMailbox" If ($Mailbox.AddNewRequestsTentatively) { If ($RecipientType -match "Equipment|Room") { $AddNewRequestsTentatively = "`$"+$Mailbox.AddNewRequestsTentatively; $cmd = $cmd + " -AddNewRequestsTentatively $AddNewRequestsTentatively" } Else { Write-Host -ForegroundColor Red "Object $($Mailbox.PrimarySmtpAddress) has value for AddNewRequestsTentatively, but is not configured as a resource mailbox." $data = "Object $($Mailbox.PrimarySmtpAddress) has value for AddNewRequestsTentatively, but is not configured as a resource mailbox." $data | Out-File $LogFile -Append } } If ($Mailbox.ProcessExternalMeetingMessages) { If ($RecipientType -match "Equipment|Room") { $ProcessExternalMeetingMessages = "`$"+$Mailbox.ProcessExternalMeetingMessages; $cmd = $cmd + " -ProcessExternalMeetingMessages $ProcessExternalMeetingMessages" } Else { Write-Host -ForegroundColor Red "Object $($Mailbox.PrimarySmtpAddress) has value for ProcessExternalMeetingMessages, but is not configured as a resource mailbox." $data = "Object $($Mailbox.PrimarySmtpAddress) has value for ProcessExternalMeetingMessages, but is not configured as a resource mailbox." $data | Out-File $Logfile -Append } } If ($Mailbox.ResourceDelegates -and $Mailbox.ResourceDelegates -notmatch '^\"\"$') { If ($RecipientType -match "Equipment|Room") { $ResourceDelegates = $Mailbox.ResourceDelegates.Replace(";",","); $cmd = $cmd + " -ResourceDelegates $ResourceDelegates" } Else { Write-Host -ForegroundColor Red "Object $($Mailbox.PrimarySmtpAddress) has value for ResourceDelegates, but is not configured as a resource mailbox." $data = "Object $($Mailbox.PrimarySmtpAddress) has value for ResourceDelegates, but is not configured as a resource mailbox." $data | Out-File $Logfile -Append } } #Write-Host "The command to be executed is: $cmd" Invoke-Expression $cmd $i++ } If (!($UseExistingSession)) { Get-PSSession | ? { $_.ConfigurationName -eq "Microsoft.Exchange" } | Remove-PSSession } Write-Host "Finished importing!" } # End Import } # End Switch |