One of our customers requested an Outlook rule for Outlook 2013 and Outlook 2016 that would redirect all email messages to a subfolder under the Inbox when the sender of the email messages was an internal sender or was listed in that users contact list.
Background
Redirecting email messages from an internal sender is a straightforward solution. Create a Transport Rule that adds a X-Header to the email, something like X-Internal. With the custom X-Header in the email message, a server side Outlook rule can be created using PowerShell that checks the header for “Internal” and then moves the email message to the specified Folder.
The challenging part of this request is creating a client side Outlook rule that determines if the sender is listed in the recipient’s contacts.
There is a big difference between a server side Outlook rule and a client side Outlook rule. More information can be found at this link:
https://blogs.technet.microsoft.com/outlooking/2015/05/01/client-side-vs-server-side-rules/
The reason we have to create a client side Outlook rule and not a server side Outlook rule is each users Outlook contact list resides in the data file which is on the perspective workstation and not on the Exchange Server.
Solution
The first task is to create a subfolder under the Inbox. There are two ways this can be done, instruct the user to create the folder or use EWS to create the folder. Dave Barrett has created a script that would perform this action – https://blogs.msdn.microsoft.com/emeamsgdev/2013/10/20/powershell-create-folders-in-users-mailboxes/.
Once the folder has been created, in our sample code below the folder name is Internal, the script can be executed against all users using a GPO or as a package from SCCM.
Known Issues
- The script will only work on the Contacts address book and not sub address books
- If Outlook isn’t open the email will not be moved
- They will need to deploy this script as part of their default image or we could create a regkey to note the script has run.
- Depending on how fast their phone updates, the user could get prompted that a new email has arrived before the email message is moved to the Internal folder but, normally the user will not be notified by the Outlook app that a new email is waiting in their Inbox
Server Side Outlook Solution
Create transport rule
Create an Exchange transport rule with the following configuration.
Create Inbox rule
New-InboxRule -Mailbox user@domain.com -Name “Internal” -HeaderContainsWords “Internal” -MoveToFolder ‘user:\inbox\internal’
More information on the rule can be found at the link below:
http://www.experts-exchange.com/questions/26880775/Exchange-2010-SP1-New-InboxRule-issue.html
Test Results – Client Side
There has to be a folder called Internal under the Inbox
No Outlook rules
Sent test message and the message went to the inbox
Added mvoss to his own contact list
Ran PowerShell script & Rule was added. You might get this prompt
Sent test message
Message went to the Internal folder
Results from OWA
Once the PowerShell script is executed, the inbox rule will be created.
A message from an internal sender was moved to the Internal folder.
PowerShell script
#########################################
# Based on PowerShell 2.0
##########################################
$RuleName = "Internal"
$Folder = "Contacts"
$RedirectFolder = "internal"
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
$olRuleType = "Microsoft.Office.Interop.Outlook.OlRuleType" -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace("MAPI")
$inbox = $namespace.getDefaultFolder($olFolders::olFolderInbox)
$rules = $outlook.session.DefaultStore.GetRules()
$rule = $rules.Create($RuleName,$olRuleType::OlRuleReceive)
$d = [System.__ComObject].InvokeMember(
"EntryID",
[System.Reflection.BindingFlags]::GetProperty,
$null,
$inbox.Folders.Item($RedirectFolder),
$null)
$MoveTarget = $namespace.getFolderFromID($d)
$MoveRuleAction = $rule.Actions.MoveToFolder
[Microsoft.Office.Interop.Outlook._MoveOrCopyRuleAction].InvokeMember(
"Folder",
[System.Reflection.BindingFlags]::SetProperty,
$null,
$MoveRuleAction,
$MoveTarget)
$MoveRuleAction.Enabled = $true
$Address = $namespace.AddressLists#("Contacts")
$Space = $address | where {$_.Name -eq 'Contacts'}
$Condition = $namespace.AddressLists
$FromCondition = $rule.Conditions.SenderInAddressList
[Microsoft.Office.Interop.Outlook._SenderInAddressListRuleCondition ].InvokeMember(
"AddressList",
[System.Reflection.BindingFlags]::SetProperty,
$null,
$FromCondition,
$Space)
$FromCondition.Enabled = $true
$rules.Save()