Report Mailbox Forwarding Enabled Users Using Exchange Online + Graph PowerShell

Mailbox forwarding is a sensitive configuration in Microsoft 365. While it’s sometimes enabled for legitimate business workflows, it’s also a common indicator of data leakage risk and account compromise. A tenant can silently accumulate forwarding-enabled mailboxes over time, and without periodic review, administrators may not know which accounts are forwarding messages externally or to other internal recipients.

One challenge is that Microsoft Graph does not expose mailbox forwarding properties through mailboxSettings, which means you can’t reliably audit forwarding using Graph cmdlets alone. However, Exchange Online PowerShell does surface forwarding settings, and once the report is generated, it can still be emailed without SMTP using Graph Send-MgUserMail.

This script combines both tools:

  • Exchange Online PowerShell → fetch forwarding settings accurately
  • Graph PowerShell → email the report without configuring SMTP

🚀 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.

i) The Script

$SenderUPN = "admin@yourtenant.onmicrosoft.com"

$Recipients = @(
    "admin@yourtenant.onmicrosoft.com",
    "securityteam@yourtenant.onmicrosoft.com"
)

Connect-ExchangeOnline

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

$Mailboxes = Get-EXOMailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox `
    -Properties ForwardingSmtpAddress,ForwardingAddress,DeliverToMailboxAndForward

$Report = @()

foreach ($mbx in $Mailboxes) {

    if ($mbx.ForwardingSmtpAddress -or $mbx.ForwardingAddress) {

        $ForwardTo = if ($mbx.ForwardingSmtpAddress) {
            $mbx.ForwardingSmtpAddress
        } else {
            $mbx.ForwardingAddress
        }

        $Report += [PSCustomObject]@{
            "User Name"                   = $mbx.DisplayName
            "User Principal Name"         = $mbx.UserPrincipalName
            "Mailbox"                     = $mbx.PrimarySmtpAddress
            "Forwarding Destination"      = $ForwardTo
            "DeliverToMailboxAndForward"  = $mbx.DeliverToMailboxAndForward
        }
    }
}

$ReportPath = "$env:TEMP\Mailbox_Forwarding_Enabled_Users.csv"

if ($Report.Count -gt 0) {
    $Report | Sort-Object "User Name" |
        Export-Csv -Path $ReportPath -NoTypeInformation -Encoding utf8
} else {
    "No licensed users with mailbox forwarding enabled were found." |
        Set-Content -Path $ReportPath -Encoding utf8
}

$Bytes = [System.IO.File]::ReadAllBytes($ReportPath)
$Utf8Bom = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::WriteAllText($ReportPath, [System.Text.Encoding]::UTF8.GetString($Bytes), $Utf8Bom)

$Count = $Report.Count
$Subject = "Mailbox Forwarding Enabled Users — $(Get-Date -Format 'yyyy-MM-dd')"

$Body = @"
Hello Team,<br><br>
Attached is the <b>Mailbox Forwarding Enabled Users</b> report.<br>
This report is generated from Exchange Online mailbox properties and mailed via Microsoft Graph.<br><br>
Total forwarding-enabled users found: <b>$Count</b><br><br>
Regards,<br>
PowerShell Automation
"@


$AttachmentContent = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes($ReportPath))
$Attachments = @(
    @{
        "@odata.type" = "#microsoft.graph.fileAttachment"
        Name          = "Mailbox_Forwarding_Enabled_Users.csv"
        ContentBytes  = $AttachmentContent
    }
)

$ToRecipients = $Recipients | ForEach-Object {
    @{ EmailAddress = @{ Address = $_ } }
}

$Message = @{
    Message = @{
        Subject = $Subject
        Body    = @{
            ContentType = "HTML"
            Content     = $Body
        }
        ToRecipients = $ToRecipients
        Attachments  = $Attachments
    }
    SaveToSentItems = "true"
}

Send-MgUserMail -UserId $SenderUPN -BodyParameter $Message

Write-Host "Mailbox forwarding report emailed successfully (EXO + Graph)." -ForegroundColor Green
                                


ii) How the Script Works

  1. Defines sender and recipients
  2. You provide:

    • a mailbox-enabled sender UPN
    • one or more recipient addresses for admins/security teams
  3. Connects to Exchange Online
    Connect-ExchangeOnline is used because mailbox forwarding settings live in Exchange, not Graph.
  4. Connects to Graph for SMTP-less email
    Connect-MgGraph with:
    • Mail.Send → required to email
    • User.Read.All → required in some tenants to resolve the sender mailbox context
  5. Retrieves all user mailboxes
    Get-EXOMailbox returns every user mailbox along with forwarding properties:
    • ForwardingSmtpAddress
    • ForwardingAddress
    • DeliverToMailboxAndForward
  6. Filters forwarding-enabled mailboxes
    Any mailbox with either forwarding property populated is added to the report.
  7. Exports an Excel-safe CSV
    The script:
    • exports UTF-8 CSV
    • rewrites with UTF-8 BOM
      so Excel always shows columns correctly.
  8. Emails CSV using Graph
    The CSV is:
    • Base64 encoded
    • attached to a Graph email payload
    • sent via Send-MgUserMail (no SMTP config needed)

iii) Further Enhancements

  • Audit inbox-rule forwarding
    Mailbox forwarding is one route. Most stealth forwarding happens through hidden Inbox rules.
  • Flag external forwarding destinations
    Add logic to highlight domains outside your tenant as “High Risk.”
  • Add last sign-in context
    Combine with SignInActivity to detect forwarding on dormant accounts.
  • Exclude known service accounts
    Filter by naming patterns or department/jobtitle to reduce noise.
  • Auto-generate remediation list
    Produce a second CSV recommending actions:
    disable forwarding / remove license / alert owner.

iv) Possible Errors & Solutions

Error Cause Solution
Connect-ExchangeOnline fails Exchange Online module not installed or outdated. Install/update and reconnect Exchange Online module.
Empty report No mailboxes currently have forwarding enabled. Valid outcome — script still sends a readable CSV.
Graph email send fails Missing Mail.Send permission or no admin consent. Grant consent and reconnect with:
Connect-MgGraph -Scopes "Mail.Send","User.Read.All"
Sender mailbox not found Sender UPN is not mailbox-enabled or lacks license. Use a licensed mailbox (admin/shared mailbox).


v) Conclusion

Mailbox forwarding is a high-value security signal in Microsoft 365, but Graph alone can’t audit it because forwarding properties aren’t exposed through Graph mailbox settings. Exchange Online PowerShell provides the accurate forwarding data, while Graph PowerShell gives a modern SMTP-less way to distribute reports automatically.

This hybrid scripting approach ensures:

  • accurate mailbox forwarding detection
  • clean Excel-friendly reporting
  • no SMTP server configuration
  • automated delivery to administrators

Run this regularly to keep forwarding governance transparent and audit-ready.


Graph PowerShell Explorer Widget

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


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex