You built the disclaimer, redirect, or BCC rule in Mail flow > Rules. Status looks fine. Users still get the old subject, external mail skips the stamp, or the redirect never happens. The usual first moves are to delete and recreate the rule, raise priority to the top, or blame "Exchange delay" forever.
Hold off. A mail flow rule (transport rule) is a short chain: rule must be Enabled and in the Mode you think → conditions and exceptions must match the real message → earlier rules must not Stop processing → the action must be visible on that message type. Most "rule not working" tickets die in State/Mode, priority, or a condition that never matches (especially distribution groups). This post walks them in order. Every step below only reads until the change table at the end.
If the problem is mailbox ForwardingSmtpAddress / inbox ForwardTo, stop here and use the monthly Exchange Online hygiene check first. That article covers forwarding and permissions. This one assumes you are debugging an organization transport rule.
TL;DR
- After you create or edit a rule, Microsoft documents that it can take 30 minutes or more before it applies consistently. Testing in the first few minutes is a common false negative.
- Read State (Enabled/Disabled) and Mode (Enforce vs Test with/without Policy Tips) before you rewrite conditions.
- Multiple conditions on one rule are AND. Multiple values inside one condition are usually OR. Exceptions are OR — one matching exception skips the whole rule.
- SentTo does not match distribution groups the way most admins expect. For "sent to members of this group," use SentToMemberOf (or the matching EAC wording).
- Confirm with message trace (look for Transport rule events) or
Test-Message -TransportRulesbefore you delete the rule.
Where in the chain did it break?
| Step | What happens | Typical symptom when it breaks |
|---|---|---|
| 1. Rule present and Enabled | Rule exists; State = Enabled | Missing from list; State = Disabled; toggle off in flyout |
| 2. Mode = Enforce (if you expect real actions) | Enforce applies delivery-impacting actions | Mode still Test…; only incident reports / Policy Tips fire |
| 3. Activation window | Activate / Deactivate dates allow processing now | Rule Enabled but outside Activate/Deactivate window |
| 4. Conditions + exceptions | Message matches all conditions and no exception | Never matches; matches everything; exception too broad |
| 5. Priority + Stop processing | Higher-priority rules run first; Stop can skip yours | Another rule at priority 0 with Stop processing |
| 6. Action vs message type | Action can run on this message (not NDR/system; content readable if needed) | Encrypted/S/MIME body; NDR; journal; rule never evaluated |
| 7. Evidence | Message trace / Test-Message / transport rule report | Trace shows no Transport rule event for your rule |
Sample three real messages (one that should match, one that should not, one reply) before you change tenant defaults.
Step 1: Read State, Mode, and the activation window
In Exchange admin center > Mail flow > Rules (https://admin.exchange.microsoft.com/#/transportrules):
| Field | Want (for a live disclaimer / redirect / reject) | If wrong |
|---|---|---|
| Status / State | Enabled | Disabled — EAC often creates rules disabled so you can review first |
| Rule mode | Enforce | Test with Policy Tips / Test without Policy Tips — delivery actions may not run |
| Activate / Deactivate | Empty, or now inside the window | Enabled but not processed outside the dates |
| Stop processing more rules | Only if you intend to halt the rest of the list | Left on from a copy of another rule |
Read-only PowerShell (ExchangeOnlineManagement, authorized session):
Connect-ExchangeOnline -ShowBanner:$false
Get-TransportRule |
Sort-Object Priority |
Select-Object Priority, Name, State, Mode, StopRuleProcessing,
ActivationDate, ExpiryDate
For one rule:
Get-TransportRule -Identity 'External disclaimer' |
Format-List Name, Priority, State, Mode, StopRuleProcessing,
ActivationDate, ExpiryDate, Comments,
FromScope, SentTo, SentToMemberOf, ExceptIf*
Map Mode carefully: in the EAC you see Enforce, Test with Policy Tips, and Test without Policy Tips. In PowerShell those commonly show as Enforce, AuditAndNotify, and Audit. If Mode is not Enforce, do not conclude the conditions are wrong when the disclaimer never lands — the rule may be matching in test mode only.
Step 2: Wait for propagation, then re-test with intention
Microsoft's manage and test docs are explicit:
- After you create or modify a mail flow rule, it might take 30 minutes or more for the change to apply to email.
- Their troubleshooting note: everything can look right and still take longer than ~15 minutes; wait and retest, and check interference from other rules.
So: note the time you saved. Send a controlled test after 30+ minutes. If you edited five minutes ago and "proved" it failed, you measured propagation, not logic.
Step 3: Read condition logic (AND / OR) and the distribution-group trap
From Microsoft's mail flow rule component model:
| Component | Logic |
|---|---|
| Multiple conditions on one rule | AND — all must match |
| One condition with multiple values | Usually OR — any value can match |
| Multiple exceptions | OR — any exception skips the actions |
| Multiple actions | All apply (unless an action ends processing) |
If you wanted "subject contains Invoice or attachment is PDF," that is two rules (or a single condition that accepts multiple values), not two separate conditions on one rule.
Distribution groups
Microsoft's own test-doc troubleshooting callout:
- Conditions that amount to The recipient is / SentTo match mailbox, mail-user, or contact recipients.
- They do not work the way people expect for distribution groups.
- Prefer The recipient is a member of / SentToMemberOf when the To line is a DG.
If your rule targets sales@contoso.com as a group and you used the person/recipient Is predicate, the rule can sit Enabled forever and never fire for normal DG mail.
Sender address location
Rules that inspect the sender can evaluate Header, Envelope, or Header or envelope. Auto-forwarded, rewritten, or connector-submitted mail often disagrees between header From and envelope MAIL FROM. If the rule "works in OWA tests" but fails for the scanner/app, read Match sender address in message before rewriting the FromScope.
Step 4: Priority and Stop processing
Rules run in Priority order (0 first). On the Rules page, order in the list is processing order.
Read-only:
Get-TransportRule | Sort-Object Priority |
Format-Table Priority, Name, State, Mode, StopRuleProcessing -AutoSize
If a higher-priority rule matches and has Stop processing more rules, your disclaimer rule never runs — even when its conditions would match. Message trace is the proof: you will see the earlier rule's Transport rule event and not yours.
Step 5: Confirm with message trace (and optional Test-Message)
Message trace in EAC
-
Mail flow > Message trace (
https://admin.exchange.microsoft.com/#/messagetrace). - Find the test message (sender, recipient, time window).
- Open details. In the event list, look for Transport rule (wording can vary slightly by UI). The action column should name what ran (disclaimer, redirect, reject, and so on).
If there is no Transport rule event for your rule:
- Conditions/exceptions did not match, or
- Mode/State/activation prevented enforcement, or
- An earlier Stop processing rule ended the chain, or
- That message type is not evaluated (see Step 6).
PowerShell detail (cloud)
Prefer the current V2 pair when available in your tenant:
$start # adjust the time window as needed = (Get-Date).AddHours(-6)
$end = Get-Date
Get-MessageTraceV2 -SenderAddress 'sender@contoso.com' `
-RecipientAddress 'user@contoso.com' `
-StartDate $start -EndDate $end |
Select-Object Received, SenderAddress, RecipientAddress, Subject, Status, MessageTraceId
Then detail for one MessageTraceId (pipeline form is fine when the set is small):
Get-MessageTraceV2 -MessageTraceId '<guid-from-above>' `
-SenderAddress 'sender@contoso.com' `
-StartDate $start -EndDate $end |
Get-MessageTraceDetailV2 |
Select-Object Date, Event, Action, Detail
Older tenants may still expose Get-MessageTrace / Get-MessageTraceDetail. Same idea: find the message, then read whether a transport-rule event named your action.
Optional hit report (last ~10 days; EventType values are tightening per Microsoft messaging — use the EventType your tenant docs require, commonly TransportRuleHits):
Get-MailDetailTransportRuleReport -StartDate $start -EndDate $end `
-TransportRule 'External disclaimer' -EventType TransportRuleHits |
Select-Object Date, SenderAddress, RecipientAddress, MessageId, TransportRule, Action |
Select-Object -First 20
If the report is empty while you expect matches, Severity / audit settings on the rule can exclude it from some reports — trust message-trace detail for a single message first.
Test-Message (simulate rules)
Exchange Online can simulate transport (and unified DLP) evaluation and email a report:
$data = [System.IO.File]::ReadAllBytes('C:\Data\test.eml')
Test-Message -MessageFileData $data `
-Sender 'megan@contoso.com' `
-Recipients 'adele@contoso.com' `
-SendReportTo 'admin@contoso.com' `
-TransportRules
Read the report before you delete conditions. Note: because the cmdlet feeds the evaluation pipeline, configured Block/Moderate-style actions can affect that test message and related notifications — use a harmless test.eml and an admin mailbox you control.
Step 6: Message types the rule will never (or only partially) see
| Message type | Mail flow rules |
|---|---|
| Normal user messages | Evaluated |
| NDRs generated by Exchange | Not processed by org mail flow rules |
| Journal reports / some arbitration traffic | Not processed like normal mail |
| S/MIME encrypted | Envelope/header conditions only; body inspection/modification generally cannot run |
| Microsoft 365 Message Encryption / RMS | Envelope always; content inspect/modify needs transport decryption configured |
If your "proof" message was an NDR or a rights-protected body and the action rewrites HTML, the rule can be healthy and still do nothing useful. Fix the test message before fixing the rule.
Also remember: Inbox rules are not mail flow rules. A client Forward/Redirect can look identical to users and never appear under Mail flow > Rules.
When a change is justified
| Finding | Prefer | Avoid |
|---|---|---|
| State = Disabled | Enable after a documented review | Deleting and recreating to "refresh" |
| Mode = Test… but you expected a disclaimer | Set Enforce after a controlled pilot | Stacking a second identical Enforce rule |
| Edited 5 minutes ago | Wait 30+ minutes; retest | Rewriting predicates every few minutes |
| Two conditions meant as OR | Split into two rules (copy is fine) | Adding more AND conditions |
| Target is a distribution group | SentToMemberOf / member-of predicate | SentTo / "is this person" against the DG |
| Higher rule has Stop processing | Adjust priority or clear Stop on the earlier rule | Creating yet another priority-0 copy |
| Trace shows no match | Fix conditions/exceptions; keep evidence | Org-wide "Apply to all messages" delete/reject experiments |
| Need external-forward hygiene, not transport | Use the EXO hygiene article | Hunting mail flow rules for mailbox ForwardingSmtpAddress |
FAQ
Why did the rule work in a Policy Tip test but never change delivery?
Test with Policy Tips / Test without Policy Tips are for evaluation without full enforcement. Delivery-impacting actions need Enforce (after you are satisfied with message-trace evidence).
How long after Save should I wait?
Microsoft documents 30 minutes or more after create/modify. Their troubleshooting note also says occasional longer delay; wait and retest before concluding the logic is wrong.
I have two conditions and want either one to match.
Multiple conditions are AND. Create two rules (EAC Duplicate is fine), one per condition, or use a single condition that accepts multiple values when the predicate supports it.
The recipient is a distribution group and SentTo never matches.
Use the member-of form (SentToMemberOf / EAC "is a member of this group"). SentTo is for mailbox, mail-user, and contact recipients.
Message trace shows a different rule, not mine.
Check Priority and Stop processing more rules on every Enabled rule above yours. Fix order before rewriting your disclaimer text.
Related posts
- A monthly Exchange Online hygiene check - external forwarding and mailbox permissions with read-only Get- cmdlets
- Exchange Online mailbox full but the online archive isn't helping - a read-first troubleshooting guide
- Does a shared mailbox need a license? The Exchange Online limits that decide it, plus a read-only audit
- Connect-MgGraph "Insufficient privileges to complete the operation" - scopes, roles, consent, and app-only, fixed in order
Free checklist
Mail flow rules often sit next to Conditional Access and secure-baseline work (guest access, external sharing, break-glass). Before you enforce related identity controls on the same tenant, the free Conditional Access pre-enforcement checklist keeps break-glass, pilot groups, and report-only review on one page:
If you want the broader monthly Exchange Online hygiene routine (forwarding surfaces, mailbox permissions, and the audit habits that catch silent BCC/redirect rules), the Exchange Online Admin Hygiene Pack pairs with this triage: https://cashflow4375.gumroad.com/l/exchange-online-admin-hygiene-pack?utm_source=devto&utm_medium=article&utm_campaign=aps_first_sale&utm_content=exchange-online-mail-flow-rule-not-working
Admin Pack Studio; not affiliated with Microsoft. Steps 1–6 only read. Pilot any Mode change to Enforce on a scoped rule first, and check current Microsoft docs for Get-MessageTraceV2 / Get-MessageTraceDetailV2 and Test-Message parameters.
Top comments (0)