diff --git a/Copy-ReceiveConnector.ps1 b/Copy-ReceiveConnector.ps1 index ea0f790..d2f8c3f 100644 --- a/Copy-ReceiveConnector.ps1 +++ b/Copy-ReceiveConnector.ps1 @@ -12,7 +12,7 @@ Please send ideas, comments and suggestions to support@granikos.eu .LINK - More information can be found at http://scripts.granikos.eu + http://scripts.granikos.eu .DESCRIPTION This script copies a receive connector from a source Exchange Server to a single target Exchange server or to all Exchange servers. @@ -33,6 +33,7 @@ 1.3 Update receive connector, if receive connector exists 1.4 Fix to handle connector updates properly 1.41 Minor fixes and update for Exchange 2016 + 1.5 Issued #2 fixed .PARAMETER ConnectorName Name of the connector the new IP addresses should be added to @@ -75,29 +76,23 @@ #> param( - [parameter(Mandatory=$true,HelpMessage='Source Exchange server to copy from')] - [string] $SourceServer, - [parameter(Mandatory=$true,HelpMessage='Name of the receive connector to copy')] - [string] $ConnectorName, - [parameter(Mandatory=$false,HelpMessage='Target Exchange server to copy the selected receive connector to')] - [string] $TargetServer = '', - [parameter(Mandatory=$true,HelpMessage='Domain Controller name')] - [string] $DomainController = '', - [parameter(Mandatory=$false,HelpMessage='Copy to all other Exchange servers')] - [switch] $CopyToAllOther, - [parameter(Mandatory=$false,HelpMessage='Copy non inherited source receive AD permissions to target receive connector')] - [switch] $CopyPermissions, - [parameter(Mandatory=$false,HelpMessage='Move receive connector to FrontEnd transport (i.e. Exchange 2007 -> Exchange 2013/2016)')] - [switch] $MoveToFrontend, - [parameter(Mandatory=$false,HelpMessage='Reset network bindings to listen on all adapters on port 25')] - [switch] $ResetBindings, - [parameter(Mandatory=$false,HelpMessage='View entire forest')] - [switch] $ViewEntireForest + [parameter(Mandatory,HelpMessage='Source Exchange server to copy from')] + [string] $SourceServer, + [parameter(Mandatory,HelpMessage='Name of the receive connector to copy')] + [string] $ConnectorName, + [string] $TargetServer = '', + [parameter(Mandatory,HelpMessage='Domain Controller name')] + [string] $DomainController = '', + [switch] $CopyToAllOther, + [switch] $CopyPermissions, + [switch] $MoveToFrontend, + [switch] $ResetBindings, + [switch] $ViewEntireForest ) -Set-StrictMode -Version Latest +# Set-StrictMode -Version Latest -Import-Module ActiveDirectory +Import-Module -Name ActiveDirectory $sourceRC = $null $secondsToWait = 60 @@ -105,19 +100,26 @@ $secondsToWait = 60 ### FUNCTIONS ----------------------------- function Request-Choice { - param([string]$Caption) - $choices = [System.Management.Automation.Host.ChoiceDescription[]]@('&Yes','&No') - [int]$defaultChoice = 1 + [CmdletBinding()] + param( + [string]$Caption = 'Really?' + ) + $choices = [System.Management.Automation.Host.ChoiceDescription[]]@('&Yes','&No') + + [int]$defaultChoice = 1 - $choiceReturn = $Host.UI.PromptForChoice($Caption, '', $choices, $defaultChoice) + $choiceReturn = $Host.UI.PromptForChoice($Caption, '', $choices, $defaultChoice) - return $choiceReturn + return $choiceReturn } function Copy-ToServer { - param( - [string]$TargetServerName - ) + [CmdletBinding()] + param( + [string]$TargetServerName = '' + ) + + if ($TargetServerName -ne '') { $sourceRC = Get-ReceiveConnector -Server $SourceServer | Where-Object{$_.Name -eq $ConnectorName} -ErrorAction SilentlyContinue @@ -125,32 +127,100 @@ function Copy-ToServer { if(($sourceRC -ne $null) -and ($targetRC -eq $null)){ - Write-Host - Write-Host "Working on $($TargetServerName) and receive connector $($ConnectorName)" + Write-Host + Write-Host ('Working on {0} and receive connector {1}' -f $TargetServerName, $ConnectorName) + + # clear permission groups for Exchange Server 2013 (thanks to Jeffery Land, https://jefferyland.wordpress.com) + $tempPermissionGroups = @($sourceRC.PermissionGroups) -split ', ' | Select-String -Pattern 'Custom' -NotMatch + $temp = ("$($tempPermissionGroups)").Replace(' ', ', ').Replace(' ','') + + if($temp -ne '') { + $sourceRC.PermissionGroups = $temp + } + + if($MoveToFrontend) { + # Move receive connector to FrontEnd Transpport + $sourceRC.TransportRole = 'FrontendTransport' + } + + if($ResetBindings) { + # Reset network bindungs to listen on all adapters using port 25 + $sourceRC.Bindings = '0.0.0.0:25' + } + + # create new Receive Connector + New-ReceiveConnector -Name $sourceRC.Name ` + -TransportRole $sourceRC.TransportRole ` + -RemoteIPRanges $sourceRC.RemoteIPRanges ` + -Bindings $sourceRC.Bindings ` + -Banner $sourceRC.Banner ` + -ChunkingEnabled $sourceRC.ChunkingEnabled ` + -DefaultDomain $sourceRC.DefaultDomain ` + -DeliveryStatusNotificationEnabled $sourceRC.DeliveryStatusNotificationEnabled ` + -EightBitMimeEnabled $sourceRC.EightBitMimeEnabled ` + -DomainSecureEnabled $sourceRC.DomainSecureEnabled ` + -LongAddressesEnabled $sourceRC.LongAddressesEnabled ` + -OrarEnabled $sourceRC.OrarEnabled ` + -Comment $sourceRC.Comment ` + -Enabled $sourceRC.Enabled ` + -ConnectionTimeout $sourceRC.ConnectionTimeout ` + -ConnectionInactivityTimeout $sourceRC.ConnectionInactivityTimeout ` + -MessageRateLimit $sourceRC.MessageRateLimit ` + -MaxInboundConnection $sourceRC.MaxInboundConnection ` + -MaxInboundConnectionPerSource $sourceRC.MaxInboundConnectionPerSource ` + -MaxInboundConnectionPercentagePerSource $sourceRC.MaxInboundConnectionPercentagePerSource ` + -MaxHeaderSize $sourceRC.MaxHeaderSize ` + -MaxHopCount $sourceRC.MaxHopCount ` + -MaxLocalHopCount $sourceRC.MaxLocalHopCount ` + -MaxLogonFailures $sourceRC.MaxLogonFailures ` + -MaxMessageSize $sourceRC.MaxMessageSize ` + -MaxProtocolErrors $sourceRC.MaxProtocolErrors ` + -MaxRecipientsPerMessage $sourceRC.MaxRecipientsPerMessage ` + -PermissionGroups $sourceRC.PermissionGroups ` + -PipeliningEnabled $sourceRC.PipeLiningEnabled ` + -ProtocolLoggingLevel $sourceRC.ProtocolLoggingLevel ` + -RequireEHLODomain $sourceRC.RequireEHLODomain ` + -RequireTLS $sourceRC.RequireTLS ` + -EnableAuthGSSAPI $sourceRC.EnableAuthGSSAPI ` + -ExtendedProtectionPolicy $sourceRC.ExtendedProtectionPolicy ` + -SizeEnabled $sourceRC.SizeEnabled ` + -TarpitInterval $sourceRC.TarpitInterval ` -EnhancedStatusCodesEnabled $sourceRC.EnhancedStatusCodesEnabled ` -Server $TargetServerName ` + -AuthMechanism $sourceRC.AuthMechanism ` + -Fqdn $sourceRC.Fqdn + + if($CopyPermissions) { + # fetch non inherited permissons from source connector + $sourcePermissions = Get-ReceiveConnector -Identity $sourceRC | Get-ADPermission | Where-Object {$_.IsInherited -eq $false} + + # we wait some time for domain controller to get stuff done + Write-Host ('Wait {0} seconds for domain controller to update' -f $secondsToWait) + Start-Sleep -Seconds $secondsToWait + + Write-Verbose -Message 'Adding AD permissions' + + # set access rights on target connector + $sourcePermissions | ForEach-Object { + Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" -DomainController $DomainController | Add-ADPermission -DomainController $DomainController -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights | Out-Null + } + } + } + elseif($sourceRC -ne $null) { + Write-Output 'Target connector already exists.' + + if((Request-Choice -Caption ('Do you want to UPDATE the receive connector {0} on server {1}?' -f $ConnectorName, $TargetServerName)) -eq 0) { + + Write-Host ('Updating server {0}' -f $TargetServerName) # clear permission groups for Exchange Server 2013 (thanks to Jeffery Land, https://jefferyland.wordpress.com) $tempPermissionGroups = @($sourceRC.PermissionGroups) -split ', ' | Select-String -Pattern 'Custom' -NotMatch $temp = ("$($tempPermissionGroups)").Replace(' ', ', ').Replace(' ','') if($temp -ne '') { - $sourceRC.PermissionGroups = $temp - } - - if($MoveToFrontend) { - # Move receive connector to FrontEnd Transpport - $sourceRC.TransportRole = 'FrontendTransport' + $sourceRC.PermissionGroups = $temp } - if($ResetBindings) { - # Reset network bindungs to listen on all adapters using port 25 - $sourceRC.Bindings = '0.0.0.0:25' - } - - # create new Receive Connector - New-ReceiveConnector -Name $sourceRC.Name ` - -TransportRole $sourceRC.TransportRole ` + Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" | Set-ReceiveConnector ` -RemoteIPRanges $sourceRC.RemoteIPRanges ` - -Bindings $sourceRC.Bindings ` -Banner $sourceRC.Banner ` -ChunkingEnabled $sourceRC.ChunkingEnabled ` -DefaultDomain $sourceRC.DefaultDomain ` @@ -182,130 +252,69 @@ function Copy-ToServer { -EnableAuthGSSAPI $sourceRC.EnableAuthGSSAPI ` -ExtendedProtectionPolicy $sourceRC.ExtendedProtectionPolicy ` -SizeEnabled $sourceRC.SizeEnabled ` - -TarpitInterval $sourceRC.TarpitInterval ` -EnhancedStatusCodesEnabled $sourceRC.EnhancedStatusCodesEnabled ` -Server $TargetServerName ` - -AuthMechanism $sourceRC.AuthMechanism + -TarpitInterval $sourceRC.TarpitInterval ` -EnhancedStatusCodesEnabled $sourceRC.EnhancedStatusCodesEnabled ` + -AuthMechanism $sourceRC.AuthMechanism ` + -Fqdn $sourceRC.Fqdn + # -Bindings $targetRC.Bindings ` + # -TransportRole $sourceRC.TransportRole ` if($CopyPermissions) { - # fetch non inherited permissons from source connector - $sourcePermissions = Get-ReceiveConnector -Identity $sourceRC | Get-ADPermission | Where-Object {$_.IsInherited -eq $false} + # fetch non inherited permissons from source connector + $sourcePermissions = Get-ReceiveConnector -Identity $sourceRC | Get-ADPermission | Where-Object {$_.IsInherited -eq $false} - # we wait some time for domain controller to get stuff done - Write-Host "Wait $($secondsToWait) seconds for domain controller to update" - Start-Sleep -Seconds $secondsToWait + # we wait some time for domain controller to get stuff done + Write-Host ('Wait {0} seconds for domain controller to update' -f $secondsToWait) + Start-Sleep -Seconds $secondsToWait - Write-Verbose 'Adding AD permissions' + Write-Verbose 'Adding AD permissions' - # set access rights on target connector - $sourcePermissions | foreach { - Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" -DomainController $DomainController | Add-ADPermission -DomainController $DomainController -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights | Out-Null - } - } - } - elseif($sourceRC -ne $null) { - Write-Output 'Target connector already exists.' - - if((Request-Choice -Caption "Do you want to UPDATE the receive connector $($ConnectorName) on server $($TargetServerName)?") -eq 0) { - Write-Host "Updating server $($TargetServerName)" - - # clear permission groups for Exchange Server 2013 (thanks to Jeffery Land, https://jefferyland.wordpress.com) - $tempPermissionGroups = @($sourceRC.PermissionGroups) -split ', ' | Select-String -Pattern 'Custom' -NotMatch - $temp = ("$($tempPermissionGroups)").Replace(' ', ', ').Replace(' ','') - - if($temp -ne '') { - $sourceRC.PermissionGroups = $temp - } - - Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" | Set-ReceiveConnector ` - -RemoteIPRanges $sourceRC.RemoteIPRanges ` - -Banner $sourceRC.Banner ` - -ChunkingEnabled $sourceRC.ChunkingEnabled ` - -DefaultDomain $sourceRC.DefaultDomain ` - -DeliveryStatusNotificationEnabled $sourceRC.DeliveryStatusNotificationEnabled ` - -EightBitMimeEnabled $sourceRC.EightBitMimeEnabled ` - -DomainSecureEnabled $sourceRC.DomainSecureEnabled ` - -LongAddressesEnabled $sourceRC.LongAddressesEnabled ` - -OrarEnabled $sourceRC.OrarEnabled ` - -Comment $sourceRC.Comment ` - -Enabled $sourceRC.Enabled ` - -ConnectionTimeout $sourceRC.ConnectionTimeout ` - -ConnectionInactivityTimeout $sourceRC.ConnectionInactivityTimeout ` - -MessageRateLimit $sourceRC.MessageRateLimit ` - -MaxInboundConnection $sourceRC.MaxInboundConnection ` - -MaxInboundConnectionPerSource $sourceRC.MaxInboundConnectionPerSource ` - -MaxInboundConnectionPercentagePerSource $sourceRC.MaxInboundConnectionPercentagePerSource ` - -MaxHeaderSize $sourceRC.MaxHeaderSize ` - -MaxHopCount $sourceRC.MaxHopCount ` - -MaxLocalHopCount $sourceRC.MaxLocalHopCount ` - -MaxLogonFailures $sourceRC.MaxLogonFailures ` - -MaxMessageSize $sourceRC.MaxMessageSize ` - -MaxProtocolErrors $sourceRC.MaxProtocolErrors ` - -MaxRecipientsPerMessage $sourceRC.MaxRecipientsPerMessage ` - -PermissionGroups $sourceRC.PermissionGroups ` - -PipeliningEnabled $sourceRC.PipeLiningEnabled ` - -ProtocolLoggingLevel $sourceRC.ProtocolLoggingLevel ` - -RequireEHLODomain $sourceRC.RequireEHLODomain ` - -RequireTLS $sourceRC.RequireTLS ` - -EnableAuthGSSAPI $sourceRC.EnableAuthGSSAPI ` - -ExtendedProtectionPolicy $sourceRC.ExtendedProtectionPolicy ` - -SizeEnabled $sourceRC.SizeEnabled ` - -TarpitInterval $sourceRC.TarpitInterval ` -EnhancedStatusCodesEnabled $sourceRC.EnhancedStatusCodesEnabled ` - -AuthMechanism $sourceRC.AuthMechanism -# -Bindings $targetRC.Bindings ` -# -TransportRole $sourceRC.TransportRole ` - - if($CopyPermissions) { - # fetch non inherited permissons from source connector - $sourcePermissions = Get-ReceiveConnector -Identity $sourceRC | Get-ADPermission | Where-Object {$_.IsInherited -eq $false} - - # we wait some time for domain controller to get stuff done - Write-Host "Wait $($secondsToWait) seconds for domain controller to update" - Start-Sleep -Seconds $secondsToWait - - Write-Verbose 'Adding AD permissions' - - # set access rights on target connector - $sourcePermissions | foreach { - Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" -DomainController $DomainController | Add-ADPermission -DomainController $DomainController -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights | Out-Null - } - } + # set access rights on target connector + $sourcePermissions | ForEach-Object { + Get-ReceiveConnector "$($TargetServerName)\$($sourceRC.Name)" -DomainController $DomainController | Add-ADPermission -DomainController $DomainController -User $_.User -Deny:$_.Deny -AccessRights $_.AccessRights -ExtendedRights $_.ExtendedRights | Out-Null + } } + } } else { - Write-Host 'There seems to be an issue with the source connector information provided.' - Write-Host "Source connector $($SourceServer)\$($ConnectorName) cannot be accessed or does not exist!" + Write-Host 'There seems to be an issue with the source connector information provided.' + Write-Host ('Source connector {0}\{1} cannot be accessed or does not exist!' -f $SourceServer, $ConnectorName) } + } + else { + Write-Host 'No target server name specified' + } } function Copy-ToAllServers { - Write-Verbose 'Copy receive connector to all other Exchange 2013 servers' + Write-Verbose 'Copy receive connector to all other Exchange 2013 servers' - $frontendServers = Get-ExchangeServer | Where-Object{($_.AdminDisplayVersion.Major -eq 15) -and (([string]$_.ServerRole).Contains('ClientAccess')) -and ($_.Name -ne $SourceServer)} | Sort-Object Name + $frontendServers = Get-ExchangeServer | Where-Object{($_.AdminDisplayVersion.Major -eq 15) -and (([string]$_.ServerRole).Contains('ClientAccess')) -and ($_.Name -ne $SourceServer)} | Sort-Object Name - foreach($server in $frontendServers){ - Write-Output "Working on server: $server" - Copy-ToServer -TargetServerName $server - } + foreach($server in $frontendServers){ + Write-Output -InputObject ('Working on server: {0}' -f $server) + Copy-ToServer -TargetServerName $server + } - Write-Verbose 'Copying to all Exchange servers done' + Write-Verbose 'Copying to all Exchange servers done' } ### MAIN ---------------------------------- if($ViewEntireForest) { - Write-Verbose "Setting ADServerSettings -ViewEntireForest $true" - Set-ADServerSettings -ViewEntireForest $true + Write-Verbose -Message ('Setting ADServerSettings -ViewEntireForest {0}' -f $true) + Set-ADServerSettings -ViewEntireForest $true } if((-not $CopyToAllOther) -and ($TargetServer -eq '')){ - Write-Output 'You need to either specific a dedicated target server using the -TargetServer ' - Write-Output 'attribute or select the -CopyToAllOther switch' - break + Write-Output 'You need to either specific a dedicated target server using the -TargetServer ' + Write-Output 'attribute or select the -CopyToAllOther switch' + break } elseif($TargetServer -ne ''){ - # Copy to a single Exchange server - Copy-ToServer -TargetServerName $TargetServer + # Copy to a single Exchange server + Copy-ToServer -TargetServerName $TargetServer } elseif($CopyToAllOther){ - # Copy to all other Exchange 2013/2016 servers - Copy-ToAllServers + # Copy to all other Exchange 2013/2016 servers + Copy-ToAllServers } \ No newline at end of file