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.

OutlookRulePost2

 

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

OutlookRulePost7

No Outlook rules

OutlookRulePost8

Sent test message and the message went to the inbox

OutlookRulePost9

Added mvoss to his own contact list

OutlookRulePost10

Ran PowerShell script & Rule was added. You might get this prompt

OutlookRulePost11

OutlookRulePost12

Sent test message

OutlookRulePost13

Message went to the Internal folder

OutlookRulePost15

 

Results from OWA

Once the PowerShell script is executed, the inbox rule will be created.

OutlookRulePost4

A message from an internal sender was moved to the Internal folder.

OutlookRulePost6

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()