Oct 9, 2026

Exchange Online: Audit Mailbox Forwarding Rules and Inbox Rules With PowerShell

5 min readApply in about 25 minIntermediate

Most business email compromise payouts don’t happen through a flashy exploit. They happen through a quiet inbox rule or a forwarding address set up weeks earlier, sitting silently in a mailbox, copying every invoice and wire instruction to an attacker while the real conversation looks completely normal to the person using it. Exchange Online makes this easy to set up and, if you’re not specifically looking, easy to miss.

There are two separate mechanisms worth auditing, and they’re easy to confuse: mailbox-level forwarding (set on the mailbox object itself) and inbox rules (set inside the mailbox, visible in Outlook’s rules list if you know to look). An attacker who gains access to a mailbox can set either one, and a thorough audit checks both.

A note on the screenshots below: I don’t have a live Exchange Online tenant in my lab, so the command output shown is a clearly labeled illustrative sample, not real tenant data. The cmdlets and their syntax are accurate and straight from Microsoft’s own documentation, you can run every one of them against your real tenant as-is.

Step 1: audit mailbox-level forwarding

This is the setting an attacker (or, sometimes, an end user trying to “fix” their own email setup) sets directly on the mailbox object. It forwards every incoming message externally, often with DeliverToMailboxAndForward set to False so the real mailbox owner never even sees a copy and has no reason to suspect anything.

Get-Mailbox -ResultSize Unlimited |
  Where-Object { $_.ForwardingSmtpAddress -ne $null -or $_.ForwardingAddress -ne $null } |
  Select-Object DisplayName, ForwardingSmtpAddress, ForwardingAddress, DeliverToMailboxAndForward
Illustrative sample PowerShell output showing a mailbox with external forwarding configured and an inbox rule forwarding to the same address, clearly labeled as a sample

Any row that returns here needs a reason. Some are legitimate (a shared mailbox forwarding to a ticketing system, for example), but any forward to a personal or external domain that nobody signed off on is worth investigating immediately, especially where DeliverToMailboxAndForward is False, since that’s the configuration specifically designed to hide the forward from the account owner.

Step 2: audit inbox rules across every mailbox

Inbox rules are set inside the mailbox itself, either by the user or by anyone who gained delegate/compromised access to it. A single mailbox can have many rules, and you want to check all of them for a ForwardTo or RedirectTo action, which is the dangerous one, as opposed to a simple “move to folder” rule.

# Single mailbox
Get-InboxRule -Mailbox [email protected] |
  Where-Object { $_.ForwardTo -or $_.RedirectTo } |
  Select-Object Name, Enabled, ForwardTo, RedirectTo

# Every mailbox in the tenant
Get-Mailbox -ResultSize Unlimited | ForEach-Object {
  Get-InboxRule -Mailbox $_.PrimarySmtpAddress |
    Where-Object { $_.ForwardTo -or $_.RedirectTo } |
    Select-Object @{N='Mailbox';E={$_.MailboxOwnerId}}, Name, Enabled, ForwardTo, RedirectTo
}

Watch for rules with vague or disguised names like “RE:” or a blank name, rules targeting an external domain, and rules that are enabled but were clearly not created by anything the user remembers configuring. Attackers frequently name these rules to blend into an existing thread so they survive a quick manual glance.

Step 3: check transport rules too

Transport rules operate at the organization level rather than per-mailbox, and a compromised admin account can create one that silently BCCs or redirects mail matching certain conditions across the whole tenant. These are rarer but far more damaging when they exist, since one rule can affect every mailbox at once.

Get-TransportRule | Where-Object { $_.RedirectMessageTo -or $_.BlindCopyTo -or $_.CopyTo } |
  Select-Object Name, State, RedirectMessageTo, BlindCopyTo, CopyTo

Step 4: lock down who can even set external forwarding

Beyond auditing what already exists, Exchange Online has a tenant-wide outbound spam filter policy setting that blocks automatic external forwarding entirely unless explicitly allowed. Most tenants should have this set to block by default, with specific exceptions handled individually rather than left wide open.

Get-HostedOutboundSpamFilterPolicy -Identity Default | Select-Object AutoForwardingMode

If this returns On rather than Off or Automatic, any mailbox in the tenant can set up external auto-forwarding without restriction, which removes a meaningful layer of protection against exactly the scenario this whole audit is looking for.

Quick guide

  1. Run the Get-Mailbox forwarding check across every mailbox.
  2. Run the Get-InboxRule loop across every mailbox for ForwardTo/RedirectTo rules.
  3. Check Get-TransportRule for any organization-wide redirect or copy rules.
  4. Confirm AutoForwardingMode on your outbound spam filter policy is not left open.
  5. For anything you find that nobody can explain, treat the mailbox as potentially compromised and reset credentials and sessions, not just the forwarding rule.

FAQ

What’s the difference between mailbox forwarding and an inbox rule?

Mailbox forwarding is a property on the mailbox object itself, set with Set-Mailbox -ForwardingSmtpAddress, and applies to everything arriving at that mailbox. An inbox rule is created inside the mailbox (visible to the user in Outlook’s rules list, though attackers often hide or rename it) and can be scoped to match specific senders or subjects rather than everything.

Why would DeliverToMailboxAndForward being False matter?

When it’s True, the real mailbox owner still receives a copy of every message alongside the forward, so a careful user might eventually notice odd messages missing or duplicated. When it’s False, the message goes only to the forwarding address, the owner never sees it, which is why it’s the configuration attackers actually use.

Can I just block all external forwarding tenant-wide?

Yes, via the outbound spam filter policy’s AutoForwardingMode setting, and Microsoft’s current guidance is to leave it off by default and handle legitimate exceptions individually rather than allowing it tenant-wide.

How often should this audit run?

Treat it as a recurring check, not a one-time cleanup. Attackers who gain access to a single mailbox often set up forwarding within minutes, so a scheduled weekly or monthly script catches new rules far faster than relying on users to notice something’s wrong themselves.

Sources