KelvinTegelaar / CIPP

CIPP is a M365 multitenant management solution
https://cyberdrain.com / https://cipp.app
GNU Affero General Public License v3.0
758 stars 4.42k forks source link

[Feature Request]: All Email Functional Path Report #2563

Closed JeremyMcM closed 2 weeks ago

JeremyMcM commented 2 weeks ago

Description of the new feature - must be an in-depth explanation of the feature you want, reasoning why, and the added benefits for MSPs as a whole.

Oftentimes we are tasked with determining what happens to an email targeting a specific email address. Finding out if that address is a user, shared mailbox, user alias, distribution list, etcetera, can be a lot of work and fraught with mistakes.

The request would be to have a report in CIPP that outputs all functional smtp addresses and shows their route and where they eventually land. If the report was exportable in a format that could be sent to customers showing all of their active addresses or could be used by us to map things out more quickly.

Thanks for considering!

PowerShell commands you would normally use to achieve above request

Here is a script we used in the past to extract this data into a CSV file. The code now gives an error because of changes on Microsoft's side, but it should show the bulk of accessing the data needed.

Connect-ExchangeOnline

$DGS = Get-EXORecipient | Where-Object {$_.PrimarySmtpAddress -inotmatch ".onmicrosoft.com"} | Sort-Object -Property RecipientTypeDetails,DisplayName
$Data = @()
$DataMemb = @()
$MembAdd = @()

$orgName = (Get-OrganizationConfig | Select-Object DisplayName).DisplayName

Foreach ($DG in $DGS) {

    Switch ($DG.RecipientTypeDetails) {

        "GuestMailUser" {
            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "GuestMailUser"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ""
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
            $Data += $DataObject
        }

        "MailContact" {
            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "External Contact"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ""
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
            $Data += $DataObject
        }

        "SharedMailbox" {
            foreach ($Member in (Get-MailboxPermission -Identity $DG.PrimarySmtpAddress | Where-Object {$_.User -inotmatch "\\"}))
            {
                $DataMemb += $Member.User
            }

            foreach ($add in $DG.EmailAddresses) {
                if (($add -inotmatch $DG.PrimarySmtpAddress) -and ($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch "SPO:")) {
                    $MembAdd += ($add -replace "smtp:", "")
                }
            }

            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "Shared Mailbox"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ($DataMemb -join "`n")
            $Data += $DataObject
            $DataMemb = @()
            $MembAdd = @()
        }

        "GroupMailbox" {
            if ($DG.DisplayName -ne "Outlook Customer Manager") {

                foreach ($Member in (Get-UnifiedGroupLinks -Identity $DG.PrimarySmtpAddress -LinkType Members))
                {
                    if ($Member.PrimarySmtpAddress -ne "") {
                        $DataMemb += $Member.PrimarySmtpAddress
                    }
                }

                foreach ($add in $DG.EmailAddresses) {
                    if (($add -inotmatch $DG.PrimarySmtpAddress) -and ($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch "SPO:")) {
                        $MembAdd += ($add -replace "smtp:", "")
                    }
                }

                $DataObject = New-Object PSObject
                $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "Microsoft 365 Group"
                $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
                $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
                $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
                $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ($DataMemb -join "`n")
                $Data += $DataObject
                $DataMemb = @()
                $MembAdd = @()
            }
        }

        "UserMailbox" {
            foreach ($add in $DG.EmailAddresses) {
                if (($add -inotmatch $DG.PrimarySmtpAddress) -and ($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch "SPO:")) {
                    $MembAdd += ($add -replace "smtp:", "")
                }
            }

            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "User Mailbox"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
            $Data += $DataObject
            $MembAdd = @()
        }
        "TeamMailbox" {
#            $DataObject = New-Object PSObject
#            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "Team Mailbox"
#            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
#            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
#            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ""
#            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
#            $Data += $DataObject
        }

        "RoomMailbox" {
            foreach ($add in $DG.EmailAddresses) {
                if (($add -inotmatch $DG.PrimarySmtpAddress) -and ($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch "SPO:")) {
                    $MembAdd += ($add -replace "smtp:", "")
                }
            }

            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "Room Mailbox"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
            $Data += $DataObject
            $MembAdd = @()
        }

        "EquipmentMailbox" {
            foreach ($add in $DG.EmailAddresses) {
                if (($add -inotmatch $DG.PrimarySmtpAddress) -and ($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch "SPO:")) {
                    $MembAdd += ($add -replace "smtp:", "")
                }
            }

            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "Equipment Mailbox"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ""
            $Data += $DataObject
            $MembAdd = @()
        }

        default {

            foreach ($Member in (Get-DistributionGroupMember -Identity $DG.PrimarySmtpAddress))
            {
                $DataMemb += $Member.PrimarySmtpAddress
            }

            foreach ($add in $DG.EmailAddresses) {
                if (($add -inotmatch ".onmicrosoft.com") -and ($add -inotmatch $DG.PrimarySmtpAddress)) {
                    $MembAdd += ($add -replace "smtp:", "")
                }
            }

            $DataObject = New-Object PSObject
            $DataObject | Add-Member -NotePropertyName "Type" -NotePropertyValue "DistributionGroup"
            $DataObject | Add-Member -NotePropertyName "Display Name" -NotePropertyValue $DG.DisplayName
            $DataObject | Add-Member -NotePropertyName "Primary Address" -NotePropertyValue $DG.PrimarySmtpAddress
            $DataObject | Add-Member -NotePropertyName "Aliases" -NotePropertyValue ($MembAdd -join "`n")
            $DataObject | Add-Member -NotePropertyName "Members" -NotePropertyValue ($DataMemb -join "`n")
            $Data += $DataObject
            $DataMemb = @()
            $MembAdd = @()
        }
    }
}

# Verify the temporary folder exists and create if missing.
if (!(Test-Path -Path "C:\Temp")) { New-Item -Path "C:\Temp" -ItemType Directory }

$pth = "C:\Temp\AllAddresses-$orgName.csv"

# Define list of invalid characters for file names.
$invalidCharacters = '/*?"<>|'

# Loop through each invalid character and remove it from the string.
foreach ($char in $invalidCharacters)
{
    # Escape the character using the [regex]::Escape() method
    $escapedChar = [regex]::Escape($char)

    # Remove the character from the string using a regex pattern
    $pth = $pth -replace "[$escapedChar]", '_'
}

$Data | Export-CSV -Path $pth -NoTypeInformation -Encoding UTF8

Get-Module -Name ExchangeOnlineManagement
Import-Module ExchangeOnlineManagement
KelvinTegelaar commented 2 weeks ago

You can actually already use the mailbox test tool for this :)