Remediation/ExchangeOnline/MAIL-FLOW-TEST.ps1
|
# UNTESTED: this script has never been run on a real tenant. Read it, try it on a test tenant first, and use it at your own risk. <# .SYNOPSIS Prepares the mail flow test and reports its delivery (procedure MAIL-FLOW-TEST). .DESCRIPTION Sending the test message belongs to the cutover: this script does not send it. Before: it checks the test addresses of the remediation settings, one internal and one external, and the sender. After, in an -Apply run: it reads the message trace of each recipient. An empty trace does not prove a failure: the trace can lag. It also gives the checks only an external mailbox can do. Risk to validate in a rehearsal: the test comes before the target accounts are opened, so the sending account is not open yet. #> $c = Open-TcRemediation $Recipients = @((Get-TcRemediationOption 'TestRecipients') | Where-Object { $_ -and $_ -notmatch '^<' }) $accepted = @(Get-TcRemediationTable 'Target' 'acceptedDomains' | ForEach-Object { ([string]$_['Domain']).ToLowerInvariant() }) foreach ($t in $c.Tenants) { Write-TcRemediationTenant $t $internalItems = @($Recipients | Where-Object { (Get-TcAddressDomain $_) -in $accepted }) $externalUsers = @($Recipients | Where-Object { (Get-TcAddressDomain $_) -notin $accepted }) Write-TcRemediationNote ("Test addresses: {0} internal, {1} external" -f $internalItems.Count, $externalUsers.Count) if (-not $internalItems.Count -or -not $externalUsers.Count) { Write-TcRemediationAlert 'TestRecipients must hold at least one real internal and one real external address in the remediation settings.' } $senderAddress = [string](Get-TcRemediationOption 'TestSender') if (-not $senderAddress) { $senderAddress = @((Get-TcMember ((@(Get-TcRemediationIdentity $t) | Select-Object -First 1)) 'rows') | Where-Object { (Get-TcMember $_ 'Decision') -eq 'Create' -and (Get-TcMember $_ 'Type') -eq 'User' } | ForEach-Object { (Get-TcMember $_ 'Target UPN') }) | Select-Object -First 1 Write-TcRemediationNote ("Sender: none in the remediation settings, the first account to create is used: {0}" -f $senderAddress) } Add-TcManualAction -Tenant $t -Object "External test $t" -Description "Confirm the mail test of $t from the external mailbox" -Instruction @( "Confirm that the message Cutover test $t arrived in the external mailbox: the module has no trace for this recipient.", 'Reply to the migrated address, to test the inbound flow through the new MX.', 'Read the headers of the message received: Authentication-Results must show spf=pass, dkim=pass and dmarc=pass.', 'Record the result in the cutover tracking.') } Invoke-TcRemediationPlan -Verify { param($t) $end = Get-Date foreach ($d in $Recipients) { $traces = @(Invoke-TcServiceCommand -Tenant 'Target' -Service Exo -Command 'Get-MessageTraceV2' -Parameters @{ RecipientAddress = $d; StartDate = $end.AddHours(-3); EndDate = $end } | Where-Object { (Get-TcText $_ 'Subject') -like "Cutover test $t*" }) if (-not $traces.Count) { New-TcRemediationResult Warning "${d}: no trace of the test for 3 hours, message trace can lag" } elseif (@($traces | Where-Object { (Get-TcText $_ 'Status') -eq 'Delivered' }).Count) { New-TcRemediationResult OK "${d}: test message delivered" } else { New-TcRemediationResult Warning ("{0}: state {1}" -f $d, (($traces | ForEach-Object { (Get-TcText $_ 'Status') } | Select-Object -Unique) -join ', ')) 'Check the MX, the accepted domains and the connectors.' } } } Close-TcRemediation |