Repository: microsoft/CSS-Exchange
File: M365/MDO/ResendFailedMail.ps1 (PowerShell)

Code before:
    } catch {
        Write-Host "Error checking Graph connection:`n$_" -ForegroundColor Red
        Write-Host "Verify that you have Microsoft.Graph.Mail and Microsoft.Graph.Users.Actions modules installed and loaded." -ForegroundColor Yellow
        Write-Host "You could use:" -ForegroundColor Yellow
        Write-Host "`tConnect-MgGraph -TenantId ""[YOUR TENANT ID HERE]"" -ClientSecretCredential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ""[YOUR APP ID HERE]"", (ConvertTo-SecureString -String ""[VALUE FIELD OF YOUR SECRET HERE]"" -AsPlainText -Force)) -NoWelcome" -ForegroundColor Yellow
        Write-Verbose "$_"
        exit
    }
    if ($null -eq $graphConnection) {
        Write-Host "Not connected to Graph" -ForegroundColor Red
        Write-Host "Verify that you have Microsoft.Graph.Mail and Microsoft.Graph.Users.Actions modules installed and loaded." -ForegroundColor Yellow
        Write-Host "You could use:" -ForegroundColor Yellow
        Write-Host "`tConnect-MgGraph -TenantId ""[YOUR TENANT ID HERE]"" -ClientSecretCredential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ""[YOUR APP ID HERE]"", (ConvertTo-SecureString -String ""[VALUE FIELD OF YOUR SECRET HERE]"" -AsPlainText -Force)) -NoWelcome" -ForegroundColor Yellow
        exit
    } elseif ($graphConnection.count -eq 1) {
        $expectedScopes = 'Mail.Read', 'Mail.Send'
        if (Test-GraphContext -Scopes $graphConnection.Scopes -ExpectedScopes $expectedScopes) {
            Write-Host "Connected to Graph"
            Write-Host "Session details"
            Write-Host "TenantID: $(($graphConnection).TenantId)"
            Write-Host "AuthType: $(($graphConnection).AuthType)"
        } else {
            Write-Host "We cannot continue without Graph Powershell session without Expected Scopes." -ForegroundColor Red
            Write-Host "Verify that you have Microsoft.Graph.Mail and Microsoft.Graph.Users.Actions modules installed and loaded." -ForegroundColor Yellow
            Write-Host "You could use:" -ForegroundColor Yellow
            Write-Host "`tConnect-MgGraph -TenantId ""[YOUR TENANT ID HERE]"" -ClientSecretCredential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ""[YOUR APP ID HERE]"", (ConvertTo-SecureString -String ""[VALUE FIELD OF YOUR SECRET HERE]"" -AsPlainText -Force)) -NoWelcome" -ForegroundColor Yellow
            exit
        }
    } else {
        Write-Host "You have more than one Graph sessions. Please use just one session." -ForegroundColor Red
        exit
    }
    if (($graphConnection.TenantId) -ne ($exoConnection.TenantId) ) {
        Write-Host "`nThe Tenant Id from Graph and EXO are different. Please use the same tenant." -ForegroundColor Red
        exit
    }
}

$acceptedDomains = $null
try {
    $acceptedDomains = Get-AcceptedDomain -ErrorAction Stop
} catch {
    Write-Host "Error getting Accepted Domains:`n$_" -ForegroundColor Red
    exit
}

if ($null -eq $acceptedDomains) {
    Write-Host "We do not get accepted domains." -ForegroundColor Red
    exit
}


Review comment (security):
We probably shouldn't be providing this as if it was an actual command within the script, our formatters should complain about it. Plus that isn't the correct way we have it documented. 

https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/rules/avoidusingconverttosecurestringwithplaintext?view=ps-modules

https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/connect-mggraph?view=graph-powershell-1.0

Code after:
            Write-Host "`tConnect-MgGraph -TenantId ""[YOUR TENANT ID HERE]"" -ClientSecretCredential `$ClientSecretCredential -NoWelcome" -ForegroundColor Yellow
            exit
        }
    } else {
        Write-Host "You have more than one Graph sessions. Please use just one session." -ForegroundColor Red
        exit
    }
    if (($graphConnection.TenantId) -ne ($exoConnection.TenantId) ) {
        Write-Host "`nThe Tenant Id from Graph and EXO are different. Please use the same tenant." -ForegroundColor Red
        exit
    }
}

if ($PsCmdlet.ParameterSetName -eq 'ResendCopyFailedDays') {
    $StartDate = (Get-Date).AddDays(-$Days)
    Write-Verbose "StartDate: $StartDate"
    $EndDate = Get-Date
    Write-Verbose "EndDate: $EndDate"
}

$traceParams = @{
    Status = "Failed"
}

if ($StartDate) { $traceParams["StartDate"] = $StartDate }
if ($EndDate) { $traceParams["EndDate"] = $EndDate }
if ($RecipientAddress ) { $traceParams["RecipientAddress"] = $RecipientAddress }
if ($SenderAddress) { $traceParams["SenderAddress"] = $SenderAddress }
if ($MessageId) { $traceParams["MessageId"] = $MessageId }

try {
    [array]$failedMessages = Get-MessageTrace @traceParams -ErrorAction Stop
} catch {
    Write-Host "Error: $_.Exception.Message" -ForegroundColor Red
    exit
}

if ($failedMessages.count -ge 1000) {
    Write-Host "We get more than 1000 messages, please limit your search." -ForegroundColor Red
    exit
}

if (-not $IncludeDuplicates) {
    [array]$failedMessages = $failedMessages | Sort-Object MessageId -Unique
}

$verifiedAcceptedSenderMessages = New-Object System.Collections.Generic.List[object]
$count = 0
$totalMessages = $failedMessages.Count
foreach ($failedMessage in $failedMessages) {
    $count++