From 96b2696ec600fd8b7c001df623f86266a38df6d8 Mon Sep 17 00:00:00 2001 From: MattB Date: Tue, 25 Feb 2025 16:09:37 -0500 Subject: [PATCH 1/7] Initial version of Get-EXOMTLReport --- Transport/Get-EXOMTLReport.ps1 | 376 +++++++++++++++++++++++++++++ docs/Transport/Get-EXOMTLReport.md | 55 +++++ 2 files changed, 431 insertions(+) create mode 100644 Transport/Get-EXOMTLReport.ps1 create mode 100644 docs/Transport/Get-EXOMTLReport.md diff --git a/Transport/Get-EXOMTLReport.ps1 b/Transport/Get-EXOMTLReport.ps1 new file mode 100644 index 0000000000..eecf739f45 --- /dev/null +++ b/Transport/Get-EXOMTLReport.ps1 @@ -0,0 +1,376 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +<# +.NOTES + Name: Get-EXOMTLReport.ps1 + Requires: User Rights + +.SYNOPSIS +Reads thru an EXO sourced Message Tracking log to generate plain text reporting on what is in the log. + +.DESCRIPTION +Reads Message Tracking Detailed logs from EXO to generate reporting on critical information that they contain. +Start-HistoricalSearch -ReportTitle -StartDate <24 hours before sent> -EndDate <24 hours after sent> -ReportType MessageTraceDetail -MessageID <message ID> -NotifyAddress <address to notify> + +Parses and provides details about the message in the MTL. +Helpful in troubleshooting message delivery issues. + +.PARAMETER MTLFile +MTL File to process. + +.PARAMETER ReportPath +Folder path for the output file. + +.PARAMETER MessageID +MessageID of a message to parse if there is more than one in the MTL. + +.OUTPUTS +Text File broken into sections that contain the output of the various data gathering run against the MTL. + +Default Output File: +$PSScriptRoot\MTL_Report_<date>.txt + +.EXAMPLE +.\Get-EXOMTLReport.ps1 -MTLPath C:\temp\MyMtl.csv -MessageID <123214124@myserver.com> + +Generates a report from the MyMtl.csv file of the message with ID <123214124@myserver.com> + +#> + +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true)] + [string] + $MTLFile, + [Parameter()] + [string] + $ReportPath = $PSScriptRoot, + [Parameter()] + [string] + $MessageID +) + +. $PSScriptRoot\..\Shared\ScriptUpdateFunctions\Test-ScriptVersion.ps1 + +### Utilities ### +function Import-MTL { + [CmdletBinding()] + [OutputType([array])] + param ( + # File path for MTL to import + [Parameter(Mandatory = $true)] + [string] + $FilePath + ) + + # Test the path of the MTL + if (!(Test-Path $FilePath)) { + Write-Error "Unable to find the specified file" -ErrorAction Stop + } + + # Try to load the file with Unicode since we need to start somewhere. + $initial_mtl = Import-Csv $FilePath -Encoding Unicode + + # If it is null then we need to try without Unicode + if ($null -eq $initial_mtl) { + Write-Output "Failed to Load as Unicode; trying normal load" + $initial_mtl = Import-Csv $FilePath + # If we still have nothing then log an error and fail + if ($null -eq $initial_mtl) { + Write-Error "Failed to load CSV" -ErrorAction Stop + } + # Need to know that we loaded without Unicode. + else { + Write-Output "Loaded CSV without Unicode" + } + } else { + Write-Output "Loaded MTL with Unicode" + } + + # Making sure the MTL contains the fields we want. + if (!(Test-CSVData -CSV $initial_mtl -ColumnsToCheck "date_time_utc", "source_context", "connector_id", "source", "event_id", "message_id", "recipient_address", "recipient_status", "recipient_count", "related_recipient_address", "reference", "message_subject", "sender_address", "return_path", "message_info", "directionality", "custom_data")) { + Write-Error "MTL is missing one or more required fields." -ErrorAction Stop + } else { Write-Output "CSV Passed Validation" } + + # Converting our strings into [DateTime] + Write-Output "Converting date_time_utc values" + for ($i = 0; $i -lt $initial_mtl.Count; $i++) { + try { + $initial_mtl[$i].date_time_utc = Get-Date($initial_mtl[$i].date_time_utc) + } catch { + Write-Error ("Problem converting date information: " + $Error) -ErrorAction Stop + } + } + + return $initial_mtl +} + +# Gather up all of the entries related to a single MessageID +function Group-ByMessageID { + [CmdletBinding()] + [OutputType([array])] + param ( + # MTL array to process + [Parameter(Mandatory = $true)] + [array]$MTL, + # MessageID to group by + [Parameter(Mandatory = $true)] + [string]$MessageID + ) + + # Filter the MTL by our messageID + [array]$Output = $MTL | Where-Object { $_.message_id -eq $MessageID } + + # Make sure we found the messageID + if ($null -eq $Output) { + Write-Error ("MessageID " + $MessageID + " not found in provide MTL.") -ErrorAction Stop + } + + ### Do we want to search the reference Colum here as well?? + + return $Output +} + +# Gather up all of the entries by recipient +function Group-ByRecipient { + [CmdletBinding()] + [OutputType([array])] + param ( + # MTL array to process + [Parameter(Mandatory = $true)] + [array] + $MTL, + # MessageID to group by + [Parameter(Mandatory = $true)] + [string] + $Recipient + ) + + # Filter the MTL by the provided recipient + [array]$Output = $MTL | Where-Object { $_.recipient_address -like ('*' + $Recipient + '*') } + + # Make sure we found the recipient + if ($null -eq $Output) { + Write-Error ("Recipient " + $Recipient + " not found in provide MTL.") -ErrorAction Stop + } + + ### Do we want to search the reference Colum here as well?? + + return $Output +} + +# Test if we have only a single MessageID provided in the MTL +function Test-UniqueMessageID { + [CmdletBinding()] + [OutputType([bool])] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [array] + $MTL + ) + + if (($MTL | Select-Object -Property message_id -Unique).count -gt 1) { + return $false + } else { + return $true + } +} + +# Determine if we have a unique recipient in the MTL +function Test-UniqueRecipient { + [CmdletBinding()] + [OutputType([bool])] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [array] + $MTL + ) + + if (($MTL | Select-Object -Property recipient_address -Unique).count -gt 1) { + return $false + } else { + return $true + } +} + +function Test-CSVData { + param( + [array]$CSV, + [array]$ColumnsToCheck + ) + + # Check to make sure we have data in the CSV + if (($null -eq $CSV) -or !($CSV.count -gt 0)) { + Write-Error "Provided CSV null or empty" -ErrorAction Stop + return $false + } + + # Read thru the data and make sure we have the needed columns + $ColumnHeaders = ($CSV | Get-Member -MemberType NoteProperty).Name.replace("`"", "") + foreach ( $ToCheck in $ColumnsToCheck) { + if (!($ColumnHeaders -contains $ToCheck)) { + # Write-Output ("Missing " + $ToCheck) + return $false + } + } + return $true +} + +function Write-OutputFile { + [CmdletBinding()] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [string] + $header, + [Parameter(Mandatory = $false)] + [string] + $message, + [Parameter(Mandatory = $false)] + [System.Management.Automation.OrderedHashtable] + $myTable + ) + + $file = $ReportFile + + Add-Content -Path $file $header.ToUpper() + Add-Content -Path $file "====================" + $myTable | Format-Table -AutoSize -HideTableHeaders | Out-String | Add-Content -Path $file +} + +### Diagnostics ### + +# Determine and report the type of client that submitted the message +function Get-StoreSubmissionData { + [CmdletBinding()] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [array] + $messageIDFilteredEvents + ) + + # Select the StoreDriver Submit event for this messageID + [array]$entry = $messageIDFilteredEvents | Where-Object { $_.source -eq "STOREDRIVER" -and $_.event_id -eq "RECEIVE" } + + # If we have more than one submission event that is a problem + if ($entry.count -gt 1){Write-Warning "Detected multiple Submission events for the same message"} + + # We can have multiple SMTP RECEIVE events if they are using add on services + foreach ($event in $entry) { + # Extract the submission data + $submission = ConvertFrom-StringData ($event.source_context -replace ",", " `n") -Delimiter ":" + + # Build the reporting hashtable + $hash = [ordered]@{ + DateTimeUTC = $event.date_time_utc + ClientType = $submission.ClientType + CreationTime = $submission.CreationTime + SubmittingMailbox = $submission.Mailbox + MessageClass = $submission.MessageClass + } + + Write-OutputFile -header "Submission Information" -myTable $hash + } +} + +function Get-MIMEData { + [CmdletBinding()] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [array] + $messageIDFilteredEvents + ) + + # Select the StoreDriver Submit event for this messageID + [array]$entry = $messageIDFilteredEvents | Where-Object { $_.source -eq "SMTP" -and $_.event_id -eq "RECEIVE" } + + # We can have multiple SMTP RECEIVE events if they are using add on services + foreach ($event in $entry) { + # If there is something wrong with the CSV we can end up with a null custom_data field, detect and skip. + if ([string]::IsNullOrEmpty($event.custom_data)) { + Write-Warning "Custom Data field Empty for SMTP RECEIVE event. Skipping" + } else { + $mimeData = (ConvertFrom-StringData ($event.custom_data -replace ";", " `n") -Delimiter "=")["S:MimeParts"].split("S:")[1].split("/") + + # Build the reporting hashtable + $hash = [ordered]@{ + DateTimeUTC = $event.date_time_utc + AttachmentCount = $mimeData[0] + EmbeddedAttachments = $mimeData[1] + NumberOfMimeParts = $mimeData[2] + EmailMessageType = $mimeData[3] + EmailMimeComplianceStatus = $mimeData[4] + } + + Write-OutputFile -header "Detected Mime Information on Submission" -myTable $hash + } + } +} + +function Get-MTLStatistics { + [CmdletBinding()] + param ( + # Parameter help description + [Parameter(Mandatory = $true)] + [array] + $messageIDFilteredEvents + ) + + # Sort the events by time. + $sortedEvents = $messageIDFilteredEvents | Sort-Object -Property "date_time_utc" + $storeReceiveEvents = $messageIDFilteredEvents | Where-Object { $_.source -eq "STOREDRIVER" -and $_.event_id -like "RECEIVE" } + $SMTPReceiveEvents = $messageIDFilteredEvents | Where-Object { $_.source -eq "SMTP" -and $_.event_id -like "RECEIVE" } + $deliveryEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "DELIVER" } + $sendExternalEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "SENDEXTERNAL" } + $SMTPResubmitEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "RESUBMIT" } + + $hash = [ordered]@{ + MessageID = $sortedEvents[0].message_id + FirstEvent = $sortedEvents[0].date_time_utc + LastEvent = $sortedEvents[-1].date_time_utc + StoreReceiveEvents = $storeReceiveEvents.count + SMTPReceiveEvents = $SMTPReceiveEvents.count + SMTPResubmitEvents = $SMTPResubmitEvents.count + DeliveryEvents = $deliveryEvents.count + SendExternalEvents = $sendExternalEvents.count + } + + Write-OutputFile -header "General MTL Statistics" -myTable $hash +} + +### Main ### + +#Import the MTL file. +$MTL = Import-MTL -FilePath $MTLFile + +# Make sure the path for the output is good +if (!(Test-Path $ReportPath)) { + Write-Error ("Unable to find report path " + $ReportPath) +} else { + $ReportFile = (Join-Path -Path $ReportPath -ChildPath ("MTL_Report_" + (Get-Date -Format FileDateTime).ToString() + ".txt")) +} + +# If no messageID was provided make sure that there is only one in the MTL +if ([string]::IsNullOrEmpty($MessageID)) { + if (!(Test-UniqueMessageID -MTL $MTL)) { + Write-Error "Multiple MessageIDs detected in MTL please using -MessageID to specify the one to examine" -ErrorAction Stop + } else { + $MessageIDFilteredMTL = $MTL + } +} +# If a messageID was provided then filter based on it +else { + $MessageIDFilteredMTL = Group-ByMessageID -MTL $MTL -MessageID $MessageID +} + +# Run the set of tests that we want to run and generate the output. +Write-Output "Generating Reporting" +Get-MTLStatistics -messageIDFilteredEvents $MessageIDFilteredMTL +Get-SToreSubmissionData -messageIDFilteredEvents $MessageIDFilteredMTL +Get-MIMEData -messageIDFilteredEvents $MessageIDFilteredMTL +Write-Output $ReportFile diff --git a/docs/Transport/Get-EXOMTLReport.md b/docs/Transport/Get-EXOMTLReport.md new file mode 100644 index 0000000000..2453c1b78e --- /dev/null +++ b/docs/Transport/Get-EXOMTLReport.md @@ -0,0 +1,55 @@ +# Get-EXOMTLReport +Download the latest release: [Get-EXOMTLReport](https://github.com/microsoft/CSS-Exchange/releases/latest/download/Get-EXOMTLReport.ps1) + +Provides information about email messages sent thru EXO by parsing a detailed message tracking log. + +## DESCRIPTION +Parses thru EXO Message Tracking log to extract detailed information about the message and present it in a more readable format. + +### Exchange Online +Recommend using [Start-HistoricalSearch](https://learn.microsoft.com/en-us/powershell/module/exchange/start-historicalsearch?view=exchange-ps) in EXO to gather a detailed Message Tracking Log for processing. + +``` PowerShell +Start-HistoricalSearch -ReportTitle "Fabrikam Search" -StartDate 8/10/2024 -EndDate 8/12/2024 -ReportType MessageTraceDetail -SenderAddress michelle@fabrikam.com -NotifyAddress chris@contoso.com +``` + +### Exchange On Premises +Does NOT work with Exchange On Premises message tracking logs. + +## PARAMETER + +**-MTLFile** + +CSV output of Message Tracking Log to process. + +**-ReportPath** + +Folder path for the output file. + +**-MessageID** + +Specifies the messageID to gather information about if there is more than one in the provided Message Tracking Log. + +## Outputs + +### Text File + +* Message Statistics +* Submission Information (from non-smtp client) +* Mime Data + +### Default Output File: +``` PowerShell +$PSScriptRoot\MTL_Report_<date>.txt +``` + +## EXAMPLE +``` PowerShell +.\Get-EXOMTLReport -MTLPath C:\temp\MyMtl.csv +``` +Generates a report to the default path from the file C:\Temp\MyMtl.csv. + +``` PowerShell +.\Measure-EmailDelayInMTL -MTLPath C:\temp\LargeMTL.csv -ReportPath C:\output -MessageID "<1231421231@server.contoso.com>" +``` +Generates a report to the c:\output directory from the file C:\Temp\LargeMTL.csv focusing on the MessageID <1231421231@server.contoso.com> From 2c0699caf757532b410b915c6766128daf03712a Mon Sep 17 00:00:00 2001 From: Matt Byrd <39496169+Canthv0@users.noreply.github.com> Date: Thu, 27 Feb 2025 15:18:10 -0500 Subject: [PATCH 2/7] Update mkdocs.yml --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index ec7c7a4bc4..6c2b2c532d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -132,6 +132,7 @@ nav: - Compute-TopExoRecipientsFromMessageTrace: Transport/Compute-TopExoRecipientsFromMessageTrace.md - ReplayQueueDatabases: Transport/ReplayQueueDatabases.md - Measure-EmailDelayInMTL: Transport/Measure-EmailDelayInMTL.md + - Get-EXOMTLReport: Transport/Get-EXOMTLReport.md theme: name: 'material' features: From ecda45ee20434e375804063f1f35665fc774b2b0 Mon Sep 17 00:00:00 2001 From: MattB <matbyrd@microsoft.com> Date: Fri, 28 Feb 2025 14:58:13 -0500 Subject: [PATCH 3/7] Added words to cspell dictionary that are needed for script. --- .build/cspell-words.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.build/cspell-words.txt b/.build/cspell-words.txt index 5030b98410..363630a0b4 100644 --- a/.build/cspell-words.txt +++ b/.build/cspell-words.txt @@ -1,8 +1,9 @@ +!scriptblock adfs Adsi amsi -Antispam anob +Antispam asmx authsspi autodiscover @@ -26,8 +27,8 @@ dumptidset DWORD eems EFORMS -EICAR eicar +EICAR Emotet emsmdb Entra @@ -37,12 +38,13 @@ Eventlog evtx Exchweb exfiltration +EXOMTL fabrikam FIPFS fips -Fsis fltmc freb +Fsis FYDIBOHF GCDO Get-AuthenticodeSignature @@ -92,8 +94,8 @@ Mgmt mitigations msdcs MSDTC -MSERT msert +MSERT msipc msrc Multiplexor @@ -109,8 +111,8 @@ notin notlike notmatch nspi -ntlm NTFS +ntlm NUMA nupkg odata @@ -138,7 +140,7 @@ Runtimes sccm Schannel SCOM -!scriptblock +SENDEXTERNAL SERVERNAME Servicehost servicelet @@ -146,6 +148,7 @@ Sids Snapin SPDLT STMP +STOREDRIVER syncall tcpip TDSDSA From f8dbd12bff25afbebd887e76da60b40ad1e2774b Mon Sep 17 00:00:00 2001 From: MattB <matbyrd@microsoft.com> Date: Fri, 28 Feb 2025 15:05:26 -0500 Subject: [PATCH 4/7] Formatting fix --- Transport/Get-EXOMTLReport.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Transport/Get-EXOMTLReport.ps1 b/Transport/Get-EXOMTLReport.ps1 index eecf739f45..3fcc40de48 100644 --- a/Transport/Get-EXOMTLReport.ps1 +++ b/Transport/Get-EXOMTLReport.ps1 @@ -257,7 +257,7 @@ function Get-StoreSubmissionData { [array]$entry = $messageIDFilteredEvents | Where-Object { $_.source -eq "STOREDRIVER" -and $_.event_id -eq "RECEIVE" } # If we have more than one submission event that is a problem - if ($entry.count -gt 1){Write-Warning "Detected multiple Submission events for the same message"} + if ($entry.count -gt 1) { Write-Warning "Detected multiple Submission events for the same message" } # We can have multiple SMTP RECEIVE events if they are using add on services foreach ($event in $entry) { From 764ade64e426fc18ef2ac927ad612d9cc6232244 Mon Sep 17 00:00:00 2001 From: MattB <matbyrd@microsoft.com> Date: Wed, 5 Mar 2025 15:54:40 -0500 Subject: [PATCH 5/7] Fixed issues that were brought up by review. --- .build/cspell-words.txt | 2 - Transport/Get-EXOMTLReport.ps1 | 92 +++++++++++----------------------- 2 files changed, 30 insertions(+), 64 deletions(-) diff --git a/.build/cspell-words.txt b/.build/cspell-words.txt index 363630a0b4..780409cedf 100644 --- a/.build/cspell-words.txt +++ b/.build/cspell-words.txt @@ -140,7 +140,6 @@ Runtimes sccm Schannel SCOM -SENDEXTERNAL SERVERNAME Servicehost servicelet @@ -148,7 +147,6 @@ Sids Snapin SPDLT STMP -STOREDRIVER syncall tcpip TDSDSA diff --git a/Transport/Get-EXOMTLReport.ps1 b/Transport/Get-EXOMTLReport.ps1 index 3fcc40de48..19652458e2 100644 --- a/Transport/Get-EXOMTLReport.ps1 +++ b/Transport/Get-EXOMTLReport.ps1 @@ -48,7 +48,10 @@ param ( $ReportPath = $PSScriptRoot, [Parameter()] [string] - $MessageID + $MessageID, + [Parameter()] + [bool] + $SkipUpdate = $false ) . $PSScriptRoot\..\Shared\ScriptUpdateFunctions\Test-ScriptVersion.ps1 @@ -74,7 +77,7 @@ function Import-MTL { # If it is null then we need to try without Unicode if ($null -eq $initial_mtl) { - Write-Output "Failed to Load as Unicode; trying normal load" + Write-Information "Failed to Load as Unicode; trying normal load" $initial_mtl = Import-Csv $FilePath # If we still have nothing then log an error and fail if ($null -eq $initial_mtl) { @@ -82,19 +85,19 @@ function Import-MTL { } # Need to know that we loaded without Unicode. else { - Write-Output "Loaded CSV without Unicode" + Write-Information "Loaded CSV without Unicode" } } else { - Write-Output "Loaded MTL with Unicode" + Write-Information "Loaded MTL with Unicode" } # Making sure the MTL contains the fields we want. if (!(Test-CSVData -CSV $initial_mtl -ColumnsToCheck "date_time_utc", "source_context", "connector_id", "source", "event_id", "message_id", "recipient_address", "recipient_status", "recipient_count", "related_recipient_address", "reference", "message_subject", "sender_address", "return_path", "message_info", "directionality", "custom_data")) { Write-Error "MTL is missing one or more required fields." -ErrorAction Stop - } else { Write-Output "CSV Passed Validation" } + } else { Write-Information "CSV Passed Validation" } # Converting our strings into [DateTime] - Write-Output "Converting date_time_utc values" + Write-Information "Converting date_time_utc values" for ($i = 0; $i -lt $initial_mtl.Count; $i++) { try { $initial_mtl[$i].date_time_utc = Get-Date($initial_mtl[$i].date_time_utc) @@ -132,34 +135,6 @@ function Group-ByMessageID { return $Output } -# Gather up all of the entries by recipient -function Group-ByRecipient { - [CmdletBinding()] - [OutputType([array])] - param ( - # MTL array to process - [Parameter(Mandatory = $true)] - [array] - $MTL, - # MessageID to group by - [Parameter(Mandatory = $true)] - [string] - $Recipient - ) - - # Filter the MTL by the provided recipient - [array]$Output = $MTL | Where-Object { $_.recipient_address -like ('*' + $Recipient + '*') } - - # Make sure we found the recipient - if ($null -eq $Output) { - Write-Error ("Recipient " + $Recipient + " not found in provide MTL.") -ErrorAction Stop - } - - ### Do we want to search the reference Colum here as well?? - - return $Output -} - # Test if we have only a single MessageID provided in the MTL function Test-UniqueMessageID { [CmdletBinding()] @@ -178,24 +153,7 @@ function Test-UniqueMessageID { } } -# Determine if we have a unique recipient in the MTL -function Test-UniqueRecipient { - [CmdletBinding()] - [OutputType([bool])] - param ( - # Parameter help description - [Parameter(Mandatory = $true)] - [array] - $MTL - ) - - if (($MTL | Select-Object -Property recipient_address -Unique).count -gt 1) { - return $false - } else { - return $true - } -} - +# Makes sure that the provided CSV file has the needed columns to be a valid MTL function Test-CSVData { param( [array]$CSV, @@ -212,14 +170,14 @@ function Test-CSVData { $ColumnHeaders = ($CSV | Get-Member -MemberType NoteProperty).Name.replace("`"", "") foreach ( $ToCheck in $ColumnsToCheck) { if (!($ColumnHeaders -contains $ToCheck)) { - # Write-Output ("Missing " + $ToCheck) + # Write-Information ("Missing " + $ToCheck) return $false } } return $true } -function Write-OutputFile { +function Write-InformationFile { [CmdletBinding()] param ( # Parameter help description @@ -273,7 +231,7 @@ function Get-StoreSubmissionData { MessageClass = $submission.MessageClass } - Write-OutputFile -header "Submission Information" -myTable $hash + Write-InformationFile -header "Submission Information" -myTable $hash } } @@ -307,7 +265,7 @@ function Get-MIMEData { EmailMimeComplianceStatus = $mimeData[4] } - Write-OutputFile -header "Detected Mime Information on Submission" -myTable $hash + Write-InformationFile -header "Detected Mime Information on Submission" -myTable $hash } } } @@ -323,10 +281,10 @@ function Get-MTLStatistics { # Sort the events by time. $sortedEvents = $messageIDFilteredEvents | Sort-Object -Property "date_time_utc" - $storeReceiveEvents = $messageIDFilteredEvents | Where-Object { $_.source -eq "STOREDRIVER" -and $_.event_id -like "RECEIVE" } + $storeReceiveEvents = $messageIDFilteredEvents | Where-Object { $_.source -eq "StoreDriver" -and $_.event_id -like "RECEIVE" } $SMTPReceiveEvents = $messageIDFilteredEvents | Where-Object { $_.source -eq "SMTP" -and $_.event_id -like "RECEIVE" } $deliveryEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "DELIVER" } - $sendExternalEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "SENDEXTERNAL" } + $sendExternalEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "SendExternal" } $SMTPResubmitEvents = $messageIDFilteredEvents | Where-Object { $_.event_id -like "RESUBMIT" } $hash = [ordered]@{ @@ -340,17 +298,27 @@ function Get-MTLStatistics { SendExternalEvents = $sendExternalEvents.count } - Write-OutputFile -header "General MTL Statistics" -myTable $hash + Write-InformationFile -header "General MTL Statistics" -myTable $hash } ### Main ### +if ($SkipUpdate) { Write-Information "Skipping Update" } +else { + # See if we have an updated version. + if (Test-ScriptVersion -AutoUpdate) { + # Update was downloaded, so stop here. + Write-Host "Script was updated. Please rerun the command." + return + } +} + #Import the MTL file. $MTL = Import-MTL -FilePath $MTLFile # Make sure the path for the output is good if (!(Test-Path $ReportPath)) { - Write-Error ("Unable to find report path " + $ReportPath) + Write-Error ("Unable to find report path " + $ReportPath) -ErrorAction Stop } else { $ReportFile = (Join-Path -Path $ReportPath -ChildPath ("MTL_Report_" + (Get-Date -Format FileDateTime).ToString() + ".txt")) } @@ -369,8 +337,8 @@ else { } # Run the set of tests that we want to run and generate the output. -Write-Output "Generating Reporting" +Write-Information "Generating Reporting" Get-MTLStatistics -messageIDFilteredEvents $MessageIDFilteredMTL Get-SToreSubmissionData -messageIDFilteredEvents $MessageIDFilteredMTL Get-MIMEData -messageIDFilteredEvents $MessageIDFilteredMTL -Write-Output $ReportFile +Write-Information $ReportFile From dd35c8ca13f62246f24d63d7fa7377b718fdb5bc Mon Sep 17 00:00:00 2001 From: MattB <matbyrd@microsoft.com> Date: Tue, 11 Mar 2025 14:25:42 -0400 Subject: [PATCH 6/7] Requested fixes --- .build/cspell-words.txt | 1 - Transport/Get-EXOMTLReport.ps1 | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.build/cspell-words.txt b/.build/cspell-words.txt index 780409cedf..554b717140 100644 --- a/.build/cspell-words.txt +++ b/.build/cspell-words.txt @@ -1,4 +1,3 @@ -!scriptblock adfs Adsi amsi diff --git a/Transport/Get-EXOMTLReport.ps1 b/Transport/Get-EXOMTLReport.ps1 index 19652458e2..81dbcd45a8 100644 --- a/Transport/Get-EXOMTLReport.ps1 +++ b/Transport/Get-EXOMTLReport.ps1 @@ -303,6 +303,10 @@ function Get-MTLStatistics { ### Main ### +# Set InformationPreference to allow Write-Information to be displayed to the screen. +$OriginalInformationPreference = $InformationPreference +$InformationPreference = 'Continue' + if ($SkipUpdate) { Write-Information "Skipping Update" } else { # See if we have an updated version. @@ -342,3 +346,6 @@ Get-MTLStatistics -messageIDFilteredEvents $MessageIDFilteredMTL Get-SToreSubmissionData -messageIDFilteredEvents $MessageIDFilteredMTL Get-MIMEData -messageIDFilteredEvents $MessageIDFilteredMTL Write-Information $ReportFile + +# Set informationPreference back to the original setting. +$InformationPreference = $OriginalInformationPreference From 40b80041b77025a6640b6cc31c6ece7b5471c56e Mon Sep 17 00:00:00 2001 From: MattB <matbyrd@microsoft.com> Date: Tue, 11 Mar 2025 14:55:33 -0400 Subject: [PATCH 7/7] Fixed spelling error --- Transport/Get-EXOMTLReport.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Transport/Get-EXOMTLReport.ps1 b/Transport/Get-EXOMTLReport.ps1 index 81dbcd45a8..5634d3e688 100644 --- a/Transport/Get-EXOMTLReport.ps1 +++ b/Transport/Get-EXOMTLReport.ps1 @@ -212,7 +212,7 @@ function Get-StoreSubmissionData { ) # Select the StoreDriver Submit event for this messageID - [array]$entry = $messageIDFilteredEvents | Where-Object { $_.source -eq "STOREDRIVER" -and $_.event_id -eq "RECEIVE" } + [array]$entry = $messageIDFilteredEvents | Where-Object { $_.source -eq "StoreDriver" -and $_.event_id -eq "RECEIVE" } # If we have more than one submission event that is a problem if ($entry.count -gt 1) { Write-Warning "Detected multiple Submission events for the same message" }