Automate Exchange Online Mailbox Forwarding Security Audits with PowerShell

Mailbox forwarding is one of the most commonly abused email features in Microsoft 365 environments. While forwarding can support legitimate business workflows, it is also frequently leveraged in:

  • Business Email Compromise (BEC) attacks
  • insider threat activity
  • silent email monitoring
  • unauthorized data exfiltration
  • compromised mailbox persistence

Attackers often configure forwarding rules to secretly redirect sensitive emails to external accounts without the user’s knowledge.

This PowerShell automation solution helps administrators perform Exchange Online mailbox forwarding security audits by detecting:

  • mailbox-level forwarding
  • inbox rule forwarding
  • external forwarding destinations
  • risky forwarding configurations
  • shared mailbox forwarding
  • multiple forwarding methods

The script generates a detailed security governance report, calculates forwarding risk levels, exports results to CSV, and automatically emails a governance summary to administrators.

🚀 Community Edition Released!

Try the M365Corner Microsoft 365 Reporting Tool — your DIY pack with 20+ out-of-the-box M365 reports for Users, Groups, and Teams.

Why Mailbox Forwarding Is a Security Risk

Unauthorized mailbox forwarding can expose organizations to:

  • sensitive data leakage
  • financial fraud
  • compliance violations
  • unauthorized email monitoring
  • persistence mechanisms used by attackers

Forwarding rules are especially dangerous because they can silently redirect:

  • invoices
  • password reset emails
  • executive communications
  • confidential business information

Regular forwarding audits help organizations detect suspicious forwarding activity before it escalates into a larger security incident.


Difference Between Mailbox Forwarding and Inbox Rule Forwarding

Mailbox forwarding and inbox rule forwarding are often confused, but they work differently.

Type Description
Mailbox Forwarding Configured at the mailbox level using forwarding addresses
Inbox Rule Forwarding Configured using mailbox inbox rules created by users

Attackers frequently abuse inbox rules because they are:

  • harder to notice
  • easy to automate
  • commonly overlooked during audits

This script audits both forwarding methods.


How Attackers Abuse Mailbox Forwarding

Compromised accounts often use forwarding rules to:

  • monitor executive communications
  • exfiltrate sensitive information
  • intercept invoices and payment requests
  • maintain persistence after password resets

Common attacker techniques include:

  • forwarding to Gmail or Yahoo accounts
  • hidden inbox rules
  • redirecting mail as attachments
  • combining multiple forwarding methods

Regular forwarding governance reviews help detect these indicators early.


Prerequisites

Install the required PowerShell modules:

                                
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Install-Module Microsoft.Graph -Scope CurrentUser
                                
                            

Connect to Exchange Online:

Connect-ExchangeOnline

Connect to Microsoft Graph:

                                
Connect-MgGraph -Scopes `
"User.Read.All",
"Mail.Read",
"Mail.Send"

                                
                            

The Script

                            
# Import required modules
Import-Module ExchangeOnlineManagement
Import-Module Microsoft.Graph

# Connect to Exchange Online
Connect-ExchangeOnline

# Verify Exchange Online connection
$EXOConnection = Get-ConnectionInformation

if (-not $EXOConnection) {
    Write-Host "Exchange Online connection failed. Please reconnect using Connect-ExchangeOnline." -ForegroundColor Red
    return
}

# Connect to Microsoft Graph
Connect-MgGraph -Scopes `
"User.Read.All",
"Domain.Read.All",
"Mail.Send"

# Export report path
$ReportPath = "C:\Reports\MailboxForwardingSecurityAudit.csv"

# Email settings
$Sender = "admin@contoso.com"
$Recipient = "securityteam@contoso.com"

# Get accepted/internal domains using Microsoft Graph
$AcceptedDomains = (
    Get-MgDomain |
    Where-Object {
        $_.IsVerified -eq $true
    }
).Id

# High-risk consumer domains
$ConsumerDomains = @(
    "gmail.com",
    "yahoo.com",
    "outlook.com",
    "hotmail.com",
    "icloud.com"
)

$AuditReport = @()

# Retrieve mailboxes
$Mailboxes = Get-EXOMailbox `
-ResultSize Unlimited `
-Properties ForwardingSMTPAddress,ForwardingAddress,RecipientTypeDetails

foreach ($Mailbox in $Mailboxes) {

    try {

        Write-Host "Processing mailbox: $($Mailbox.UserPrincipalName)" -ForegroundColor Cyan

        $ForwardingMethods = @()
        $Severity = "Low"
        $RiskScore = 0
        $Recommendations = @()

        $ForwardDestination = $null
        $ForwardingType = $null
        $DestinationCategory = "None"

        # Mailbox-level forwarding detection
        if ($Mailbox.ForwardingSMTPAddress) {

            $ForwardDestination = $Mailbox.ForwardingSMTPAddress.ToString()
            $ForwardingType = "Mailbox Forwarding"

            $ForwardingMethods += "Mailbox Forwarding"
            $RiskScore += 30
            $Recommendations += "Review mailbox-level forwarding"

            # Clean forwarding address
            $CleanForwardingAddress = $ForwardDestination -replace "smtp:", ""

            # Extract domain
            $ForwardDomain = (
                $CleanForwardingAddress -split "@"
            )[-1].ToLower()

            # Internal vs external forwarding
            if ($AcceptedDomains -contains $ForwardDomain) {

                $DestinationCategory = "Internal"

                if ($Severity -ne "Critical") {
                    $Severity = "Medium"
                }
            }
            else {

                $DestinationCategory = "External"
                $Severity = "High"
                $RiskScore += 40
                $Recommendations += "Investigate external forwarding immediately"

                if ($ConsumerDomains -contains $ForwardDomain) {

                    $DestinationCategory = "Consumer Email Domain"
                    $RiskScore += 20
                    $Recommendations += "Review suspicious consumer email forwarding"
                }
            }
        }

        # Inbox rule forwarding detection
        $InboxRules = Get-InboxRule `
        -Mailbox $Mailbox.UserPrincipalName `
        -ErrorAction SilentlyContinue

        $ForwardingRules = $InboxRules | Where-Object {
            $_.ForwardTo -or
            $_.RedirectTo -or
            $_.ForwardAsAttachmentTo
        }

        if ($ForwardingRules) {

            $ForwardingMethods += "Inbox Rule Forwarding"
            $RiskScore += 35

            if ($Severity -ne "Critical") {
                $Severity = "High"
            }

            $Recommendations += "Review suspicious inbox forwarding rules"
        }

        # Multiple forwarding method detection
        if ($ForwardingMethods.Count -gt 1) {

            $Severity = "Critical"
            $RiskScore += 30
            $Recommendations += "Investigate possible compromise activity"
        }

        # Shared mailbox detection
        if ($Mailbox.RecipientTypeDetails -eq "SharedMailbox") {

            $RiskScore += 10
            $Recommendations += "Validate forwarding necessity for shared mailbox"
        }

        # Add only mailboxes with forwarding activity
        if ($ForwardingMethods.Count -gt 0) {

            $AuditReport += [PSCustomObject]@{
                Mailbox                 = $Mailbox.UserPrincipalName
                DisplayName             = $Mailbox.DisplayName
                MailboxType             = $Mailbox.RecipientTypeDetails
                ForwardingType          = $ForwardingMethods -join "; "
                ForwardDestination      = $ForwardDestination
                DestinationCategory     = $DestinationCategory
                Severity                = $Severity
                ForwardingRiskScore     = $RiskScore
                Recommendations         = $Recommendations -join "; "
            }
        }
    }

    catch {

        $AuditReport += [PSCustomObject]@{
            Mailbox                 = $Mailbox.UserPrincipalName
            DisplayName             = $Mailbox.DisplayName
            MailboxType             = $Mailbox.RecipientTypeDetails
            ForwardingType          = "Audit Failure"
            ForwardDestination      = "N/A"
            DestinationCategory     = "Unknown"
            Severity                = "High"
            ForwardingRiskScore     = 0
            Recommendations         = $_.Exception.Message
        }

        Write-Host "Error processing mailbox: $($Mailbox.UserPrincipalName)" -ForegroundColor Red
        Write-Host $_.Exception.Message
    }
}

# Export report
$AuditReport | Export-Csv `
-Path $ReportPath `
-NoTypeInformation `
-Encoding UTF8

Write-Host "Mailbox forwarding security report exported successfully." -ForegroundColor Green

# Governance statistics
$TotalForwardingMailboxes = $AuditReport.Count

$ExternalForwarding = (
    $AuditReport |
    Where-Object {
        $_.DestinationCategory -match "External|Consumer"
    }
).Count

$CriticalFindings = (
    $AuditReport |
    Where-Object {
        $_.Severity -eq "Critical"
    }
).Count

$InboxRuleForwarding = (
    $AuditReport |
    Where-Object {
        $_.ForwardingType -match "Inbox Rule Forwarding"
    }
).Count

# HTML preview
$HtmlPreview = (
    $AuditReport |
    Select-Object -First 10 |
    ConvertTo-Html -Fragment
)

# Email body
$EmailBody = @"
<html>
<body>

<h2>Exchange Online Mailbox Forwarding Security Audit</h2>

<p>The automated mailbox forwarding security audit has completed successfully.</p>

<ul>
<li>Total Mailboxes with Forwarding: $TotalForwardingMailboxes</li>
<li>External Forwarding Detected: $ExternalForwarding</li>
<li>Critical Security Findings: $CriticalFindings</li>
<li>Inbox Rule Forwarding Detected: $InboxRuleForwarding</li>
</ul>

<p>Below is a preview of the first 10 mailboxes with forwarding activity:</p>

$HtmlPreview

</body>
</html>
"@

# Send email report
$params = @{
    message = @{
        subject = "Exchange Online Mailbox Forwarding Security Audit"

        body = @{
            contentType = "HTML"
            content = $EmailBody
        }

        toRecipients = @(
            @{
                emailAddress = @{
                    address = $Recipient
                }
            }
        )

        attachments = @(
            @{
                "@odata.type" = "#microsoft.graph.fileAttachment"
                name          = "MailboxForwardingSecurityAudit.csv"
                contentBytes  = [System.Convert]::ToBase64String(
                    [System.IO.File]::ReadAllBytes($ReportPath)
                )
            }
        )
    }

    saveToSentItems = "true"
}

Send-MgUserMail `
-UserId $Sender `
-BodyParameter $params

Write-Host "Mailbox forwarding security audit emailed successfully." -ForegroundColor Green

How the Script Works

  1. Imports Required Modules and Establishes Connections
  2. The script imports:

    • ExchangeOnlineManagement
    • Microsoft.Graph

    and establishes connections to:

    • Exchange Online
    • Microsoft Graph

    using: Connect-ExchangeOnline and Connect-MgGraph

    This enables the script to retrieve:

    • mailbox forwarding configurations
    • inbox rules
    • Microsoft 365 accepted domains
    • email reporting capabilities

    before the security audit begins.

  3. Verifies Exchange Online Connectivity
  4. Before retrieving mailboxes, the script validates whether the Exchange Online session is active using:

    Get-ConnectionInformation

    If the Exchange Online connection fails, the script stops execution and prompts the administrator to reconnect.

    This prevents:

    • incomplete audit results
    • mailbox retrieval failures
    • Exchange Online session-related errors

    during execution.

  5. Retrieves Internal Microsoft 365 Domains
  6. Instead of using Get-AcceptedDomain, the script retrieves verified Microsoft 365 domains using Microsoft Graph:

    Get-MgDomain

    These domains are treated as:

    • trusted internal domains
    • approved forwarding destinations

    This allows the script to accurately classify forwarding destinations as:

    • internal
    • External
    • Consumer Email Domains

    during risk evaluation.

  7. Retrieves Exchange Online Mailboxes
  8. The script retrieves all Exchange Online mailboxes using:

    Get-EXOMailbox

    This includes:

    • user mailboxes
    • shared mailboxes
    • other mailbox types

    The script also retrieves:

    • mailbox forwarding addresses
    • recipient types
    • forwarding-related properties

    required for the audit.

  9. Detects Mailbox-Level Forwarding
  10. Detects Mailbox-Level Forwarding

    • ForwardingSMTPAddress
    • ForwardingAddress

    If mailbox forwarding is configured, the script:

    • records the forwarding destination
    • identifies forwarding type
    • calculates forwarding risk
    • generates remediation recommendations

    Mailbox-level forwarding is one of the most common indicators of:

    • unauthorized email redirection
    • insider threat activity
    • suspicious forwarding behavior
  11. Classifies Internal and External Forwarding
  12. The script extracts the forwarding domain from the forwarding address and compares it against verified Microsoft 365 domains.

    Forwarding destinations are classified as:

    • Internal
    • External
    • Consumer Email Domain

    Examples of consumer email domains include:

    • gmail.com
    • yahoo.com
    • outlook.com
    • hotmail.com
    • icloud.com

    External and consumer-domain forwarding configurations receive higher risk scores because they may indicate:

    • data exfiltration
    • compromised accounts
    • suspicious forwarding activity
  13. Detects Inbox Rule Forwarding
  14. Inbox rules are audited using:

    Get-InboxRule

    The script identifies forwarding-related inbox rules such as:

    • ForwardTo
    • RedirectTo
    • ForwardAsAttachmentTo

    Inbox rule forwarding is especially important because attackers frequently use hidden forwarding rules to:

    • monitor sensitive communications
    • maintain persistence
    • silently exfiltrate emails

    Detected inbox rule forwarding configurations receive elevated risk scores.

  15. Detects Multiple Forwarding Methods
  16. The script identifies mailboxes using multiple forwarding mechanisms simultaneously, such as:

    • mailbox-level forwarding
    • inbox rule forwarding

    Mailboxes containing multiple forwarding methods are automatically classified as:

    Critical

    because this behavior may indicate:

    • account compromise
    • advanced persistence techniques
    • unauthorized monitoring activity

    These mailboxes receive higher forwarding risk scores and remediation recommendations.

  17. Identifies Shared Mailboxes with Forwarding
  18. The script checks mailbox types using:

    RecipientTypeDetails

    Shared mailboxes receive additional risk weighting because:

    • they are commonly overlooked
    • they often contain sensitive operational data
    • they are frequent targets during compromise investigations

    This improves security visibility across non-user mailbox types.

  19. Calculates Forwarding Risk Scores
  20. Each mailbox receives a Forwarding Risk Score based on:

    • external forwarding
    • consumer email forwarding
    • inbox rule forwarding
    • multiple forwarding methods
    • shared mailbox exposure

    Higher scores indicate:

    • elevated forwarding risks
    • suspicious forwarding behavior
    • potential compromise indicators

    This helps administrators prioritize investigations and remediation activities.

  21. Generates Security Governance Reports
  22. The script generates a detailed mailbox forwarding security report containing:

    • mailbox names
    • forwarding methods
    • forwarding destinations
    • destination classifications
    • severity levels
    • risk scores
    • remediation recommendations

    The report is exported using:

    Export-Csv

    This provides:

    • operational visibility
    • auditability
    • compliance tracking
    • forwarding governance reporting
  23. Emails Security Audit Summaries Automatically
  24. The script automatically:

    • exports the CSV report
    • generates HTML security summaries
    • embeds governance statistics
    • emails the forwarding audit report

    The email includes:

    • total forwarding mailboxes
    • external forwarding detections
    • critical security findings
    • inbox rule forwarding detections

    This makes the solution ideal for:

    • recurring security audits
    • BEC investigations
    • compliance reviews
    • Exchange Online threat monitoring
    • mailbox forwarding governance automation

Possible Errors and Solutions

Error Cause Solution
Access Denied The account lacks Exchange Online or Graph permissions. Ensure the account has:
  • Exchange Administrator permissions
  • Mail.Read permission
  • Mail.Send permission
The term 'Get-InboxRule' is not recognized Exchange Online PowerShell module is not installed or connected. Reconnect using:
Connect-ExchangeOnline
Insufficient privileges to complete the operation Microsoft Graph permissions are missing. Reconnect using:
Connect-MgGraph -Scopes `
"User.Read.All",
"Mail.Read",
"Mail.Send"
and ensure admin consent is granted.

Conclusion

Mailbox forwarding remains one of the most important Exchange Online security indicators for detecting:

  • compromised accounts
  • insider threats
  • unauthorized data exfiltration
  • suspicious email activity

This PowerShell automation solution helps organizations:

  • detect risky forwarding configurations
  • identify suspicious inbox rules
  • classify external forwarding risks
  • prioritize investigations
  • automate mailbox forwarding governance reviews

By automating Exchange Online mailbox forwarding security audits, administrators can strengthen Microsoft 365 email security and improve visibility into suspicious forwarding activity across the organization.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                            


                            


                            

© Created and Maintained by LEARNIT WELL SOLUTIONS. All Rights Reserved.