diff --git a/README.md b/README.md index 0d36e15..787c693 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ # Exchange-Rules-Migrator -Script for migrating Exchange inbox rules before a mailbox is moved to a different forest. \ No newline at end of file +This PowerShell script was originally developed when I was working in an Exchange support team at Microsoft. When an Exchange mailbox is moved between different forests, any saved inbox rules which refer to mailboxes internal to the user's forest will break, because intra-forest rules default to the **LegacyDN** format, which looks like `[EX:/distinguished/name]`, rather than regular SMTP addresses. + +This script connects to the user's current mailbox to determine the primary SMTP address for every LegacyDN reference in the mailbox's inbox rules. It then updates the rule on the server with the correct SMTP address, thereby mitigating the rules-breaking consequence of moving a mailbox between forests. + +This script relies on the user having PowerShell access to their Exchange mailbox. Details on accessing Exchange over PowerShell may be found [here](https://docs.microsoft.com/en-us/powershell/exchange/connect-to-exchange-servers-using-remote-powershell&view=exchange-ps). \ No newline at end of file diff --git a/migrate-rules.ps1 b/migrate-rules.ps1 new file mode 100644 index 0000000..567843c --- /dev/null +++ b/migrate-rules.ps1 @@ -0,0 +1,57 @@ +$uri = "https://your.mailbox.server/powershell" +$mbx = "username@domain.com" + +$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $uri -Authentication Basic -Credential $cred -AllowRedirection +Import-PSSession $session + +# Get existing mailbox rules +$rules = Get-InboxRule -Mailbox $mbx + +# Get properties that will contain an address +$params = 'ExceptIfFrom','ExceptIfSentTo','ForwardAsAttachmentTo','ForwardTo','From','RedirectTo','SentTo' + +# SMTP format is {"Display Name" [SMTP:alias@domain.tld]} +# LegacyDN format is {"Display Name" [EX:/distinguished/name]} + +# we need to identify every rule that contains a legacyDN in any of the members that can contain an SMTP address + +# pull every rule that contains a value for any of the address inboxrule properties + +# iterate through rules +foreach ($rule in $rules) +{ + # grab rule identity - need this for Set-InboxRule + $ruleid = $rule.RuleIdentity + # iterate through each address parameter + foreach ($param in $params) + { + # assign rule.parameter to a variable for convenience + $rparam = $rule.$param + + # if rparam contains a value, do stuff + if ($rparam) + { + # iterate through array of addresses in $rparam - we need the index of the array for this one + for ($i = 0; $i -lt $rparam.count; $i++) + { + #check if EX or SMTP + if ($rparam[$i] -clike "*EX*") + { + # extract the DN from the output + $legacydn = ($rparam[$i] -csplit '\[EX\:')[1] -Replace "]", "" + + # get the SMTP address for each DN + $smtp = Get-Recipient $legacydn | Select-Object PrimarySMTPAddress + + # replace DN with SMTP address + $rparam[$i] = $rparam[$i] -replace '\[(.*?)\]',('[SMTP:'+$smtp.PrimarySMTPAddress.ToString()+']') + } + } + + # now that our $rules variable has been updated, we SHOULD be able to take the same rule by ID and update the same parameter + $ruleparam = @{$param = $rparam} + + Set-InboxRule $ruleid @ruleparam -Mailbox $mbx + } + } +} \ No newline at end of file