Public/Get-M365MailForwarding.ps1
|
function Get-M365MailForwarding { <# .SYNOPSIS Finds inbox rules that forward or redirect mail to external recipients. .DESCRIPTION Scans users' inbox message rules via Microsoft Graph and returns rules whose forward / redirect action targets a recipient outside the tenant's verified domains - a classic account-compromise indicator. Read-only. Requires MailboxSettings.Read. Note: scanning every mailbox makes one call per user and can be slow on large tenants. Use -UserId to scope to a single user. .PARAMETER UserId Restrict the scan to a single user (UPN or id). .EXAMPLE Get-M365MailForwarding .EXAMPLE Get-M365MailForwarding -UserId marta@contoso.ch #> [CmdletBinding()] [OutputType([pscustomobject])] param([string]$UserId) Assert-TTGraph Write-TTLog -Level INFO -Message "Scanning inbox rules for external forwarding ..." # Tenant verified domains $domains = @() try { $domains = @((Get-TTGraphCollection 'https://graph.microsoft.com/v1.0/domains?$select=id').id) } catch { } $domainSet = @{}; foreach ($d in $domains) { if ($d) { $domainSet[$d.ToLower()] = $true } } if ($UserId) { $users = @([pscustomobject]@{ Id = $UserId; UPN = $UserId; Name = $UserId }) } else { $users = Get-MgUser -All -Filter "accountEnabled eq true" -Property 'id,displayName,userPrincipalName,mail' -ErrorAction Stop | Where-Object { $_.Mail } | Select-Object @{N = 'Id'; E = { $_.Id } }, @{N = 'UPN'; E = { $_.UserPrincipalName } }, @{N = 'Name'; E = { $_.DisplayName } } } function Get-Recips { param($arr) @($arr) | ForEach-Object { $_.emailAddress.address } | Where-Object { $_ } } function Test-External { param($addr) if (-not $addr -or $addr -notmatch '@') { return $false } $dom = ($addr -split '@')[-1].ToLower() return -not $domainSet.ContainsKey($dom) } foreach ($u in $users) { $rules = $null try { $rules = Get-TTGraphCollection "https://graph.microsoft.com/v1.0/users/$($u.Id)/mailFolders/inbox/messageRules" } catch { continue } foreach ($rule in @($rules)) { $act = $rule.actions if (-not $act) { continue } $recips = @() $action = @() if ($act.forwardTo) { $recips += Get-Recips $act.forwardTo; $action += 'forward' } if ($act.redirectTo) { $recips += Get-Recips $act.redirectTo; $action += 'redirect' } if ($act.forwardAsAttachmentTo) { $recips += Get-Recips $act.forwardAsAttachmentTo; $action += 'forwardAsAttachment' } $ext = @($recips | Where-Object { Test-External $_ } | Select-Object -Unique) if (-not $ext) { continue } [pscustomobject]@{ User = $u.Name UPN = $u.UPN Rule = $rule.displayName Action = ($action -join ', ') External = $ext Enabled = [bool]$rule.isEnabled RuleId = $rule.id UserId = $u.Id } } } } |