Pretend you're taking a Microsoft exam:
Scenario: "You are the Exchange administrator for your organization... ".
Exchange has the Content Filter Agent (CFA), and the Edge Transport Server role designed to be a non-domain-joined mail gateway, located in perimeter networks. However, the Unix/Linux/Security folks in your organization don't trust Exchange to do the filtering (or act as the mail gateway). They insist on using open source anti-spam software, such as SpamAssasin (yes Eric, I remember CRM114 - the Controllable Regex Mutilator... and all the cool stuff you can command it to do. Just to set the record straight, I was suitably impressed back then, and continue to be so till this day.. :) on the non-Exchange SMTP gateways. After tweaking it for a number of weeks, they are able to make it work the way they want it to, or are close to it. It's implementation time!
Their solution is to insert an X-header in messages that looks like this:
X-Spam-Status:yesThat's it. Their job ends there.
As the Exchange team/administrator, your job is to ensure messages with that header end up in users' Junk Mail folder.
Exchange Server 2003 did not provide any way, out-of-the-box, to be able to inspect message headers and stamp SCL. To add some contextual fun - back then, our "solution" was a doc that showed the end-users how to create an Outlook rule to move such messages to Junk Mail. Only if Exchange/Windows admins could code... I can hear you think.
Creating a Transport Rule: Exchange Server 2007's Transport Rules functionality allows you to accomplish this easily. Here's how:
1. Fire up EMC | Organization Config | Hub Transport | Transport Rules tab
2. Click on New Transport Rule in the Action pane
3. Give the new rule a name, add a comment if you wish
4. In the Conditions page, select the condition when a message header contains specific words
5. In the Step 2 edit box, click on the message header link
6. Type X-Spam-Status | click OK
7. In the edit box, click on the specific words link
8. Type yes | click OK | click Next
9. In the Actions page, select the action set the spam confidence level to value
10. In the rule description, click on the 0 link and add a value that's above your SCLJunkThreshold | click Next
11. On the Exceptions page, click Next if you do not want any exceptions to this rule
12. Click New | click Finish to close the wizard
Or you can use the following commands:
$condition = Get-TransportRulePredicate HeaderContains
$condition.MessageHeader = "X-Spam-Status"
$condition.words = @("yes")
$action = Get-TransportRuleAction SetSCL
$action.SCLValue = 5
new-TransportRule "Stamp SCL" -condition @($condition) -action @($action)
Disable-TransportAgent "Content Filter Agent"Alternatively, you can leave the CFA enabled, but disable the Delete, Reject and Quarantine actions.
Set-ContentFilterConfig -SCLDeleteEnabled $false -SCLRejectEnabled $false -SCLQuarantineEnabled $falseSend a test message with the X-header X-Spam-Status:yes. The message has the SCL value set by the Transport Rule. If it is above the SCLJunkThreshold, it should be delivered to the Junk Mail folder.
Why this doesn't work with Delete, Reject or Quarantine thresholds enabled?
The Content Filter Agent fires on the EndOfData SMTP event. On Hub Transport servers, the Transport Rules Agent fires on the OnRoutedMessage event. If the CFA is left enabled, along with any of the above actions, messages may get deleted, rejected or quarantined. The Transport Rules Agent never gets to see deleted and rejected messages at all.
What about quarantined messages?
It's understandable if the message is already deleted or rejected - there's nothing left for the Transport Rule agent to act on! However, why doesn't the agent act on quarantined messages? With Pipeline Tracing turned on, I spent some precious cycles trying to unravel the mystery, with little success. As it turned out (thanks to helpful Exchange team folks for pointing out... ), I was overlooking the obvious - Quarantined messages are wrapped in an NDR "envelope". If you've ever logged into the quarantine mailbox and looked at quarantined messages, you know what these look like. (Related post: "HOW TO: Expose original senders and recipients of quarantined messages") The Transport Rules Agent does not see the original message headers, including our X-Spam-Status header. As a result, the rule never fires.
Life on the Edge
If using an Edge Transport server in the mix, things change. The Edge Rule agent fires on the EndOfData event, unlike Hub Transport servers. When two transport agents fire on the same SMTP event, you can set the priorities of each accordingly so one fires before the other. This is described in "How to Make the SCL Value Available to Edge Transport Rules" in Exchange Server 2007 documentation.
However, it's a lot simpler to just disable the Content Filter Agent. This meets the requirements of this scenario, where anti-spam filtering is done by 3rd-party anti-spam filters and Exchange isn't required to do any filtering at all.