Skip to content

Commit a0930bf

Browse files
authored
Merge pull request #2527 from microsoft/Nickul-AddGetAllMessageTraceScript
Add Get-AllMessageTraceResults script and documentation
2 parents f88378b + c06780b commit a0930bf

3 files changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
[CmdletBinding()]
5+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "")]
6+
[OutputType([object[]])]
7+
param(
8+
[Parameter(Mandatory)]
9+
[DateTime]$StartDate,
10+
11+
[Parameter(Mandatory)]
12+
[DateTime]$EndDate,
13+
14+
[Parameter()]
15+
[string]$FromIP,
16+
17+
[Parameter()]
18+
[string[]]$MessageId,
19+
20+
[Parameter()]
21+
[guid]$MessageTraceId,
22+
23+
[Parameter()]
24+
[string[]]$RecipientAddress,
25+
26+
[Parameter()]
27+
[string[]]$SenderAddress,
28+
29+
[Parameter()]
30+
[ValidateSet("Delivered", "Expanded", "Failed", "FilteredAsSpam", "GettingStatus", "Pending", "Quarantined")]
31+
[string[]]$Status,
32+
33+
[Parameter()]
34+
[string]$Subject,
35+
36+
[Parameter()]
37+
[ValidateSet("Contains", "StartsWith", "EndsWith")]
38+
[string]$SubjectFilterType,
39+
40+
[Parameter()]
41+
[string]$ToIP,
42+
43+
[Parameter()]
44+
[ValidateRange(1, 5000)]
45+
[int]$PageSize = 5000,
46+
47+
[Parameter()]
48+
[ValidateRange(1, 2147483647)]
49+
[int]$TimeoutMinutes = 30
50+
)
51+
52+
$timeout = (Get-Date).AddMinutes($TimeoutMinutes)
53+
$page = 1
54+
$allResults = [System.Collections.Generic.List[object]]::new()
55+
56+
# Build splat from bound parameters, excluding our custom ones
57+
$splatParams = @{}
58+
$excludeParams = @("TimeoutMinutes", "PageSize", "Verbose", "Debug", "ErrorAction", "WarningAction",
59+
"InformationAction", "ErrorVariable", "WarningVariable",
60+
"InformationVariable", "OutVariable", "OutBuffer", "PipelineVariable")
61+
62+
foreach ($key in $PSBoundParameters.Keys) {
63+
if ($key -notin $excludeParams) {
64+
$splatParams[$key] = $PSBoundParameters[$key]
65+
}
66+
}
67+
68+
$splatParams["ResultSize"] = $PageSize
69+
70+
Write-Progress -Activity "Fetching message trace data" -Status "Page $page..."
71+
$rawResults = @(Get-MessageTraceV2 @splatParams 3>&1)
72+
$results = @($rawResults | Where-Object { $_ -isnot [System.Management.Automation.WarningRecord] })
73+
foreach ($w in ($rawResults | Where-Object { $_ -is [System.Management.Automation.WarningRecord] })) {
74+
Write-Verbose "Get-MessageTraceV2 warning (page $page): $w"
75+
}
76+
if ($results) { $allResults.AddRange($results) }
77+
78+
$timedOut = $false
79+
while ($results.Count -eq $PageSize) {
80+
if ((Get-Date) -ge $timeout) {
81+
$timedOut = $true
82+
break
83+
}
84+
$page++
85+
$lastResult = $results[-1]
86+
$splatParams["StartingRecipientAddress"] = $lastResult.RecipientAddress
87+
$splatParams["EndDate"] = $lastResult.Received
88+
Write-Progress -Activity "Fetching message trace data" -Status "Retrieved $($allResults.Count) messages (page $page)..."
89+
$rawResults = @(Get-MessageTraceV2 @splatParams 3>&1)
90+
$results = @($rawResults | Where-Object { $_ -isnot [System.Management.Automation.WarningRecord] })
91+
foreach ($w in ($rawResults | Where-Object { $_ -is [System.Management.Automation.WarningRecord] })) {
92+
Write-Verbose "Get-MessageTraceV2 warning (page $page): $w"
93+
}
94+
if ($results) { $allResults.AddRange($results) }
95+
}
96+
97+
Write-Progress -Activity "Fetching message trace data" -Completed
98+
99+
if ($timedOut) {
100+
Write-Warning "Timed out after $TimeoutMinutes minutes with more results available. Returning $($allResults.Count) results collected so far."
101+
}
102+
103+
Write-Verbose "Total messages retrieved: $($allResults.Count)"
104+
return $allResults
105+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Get-AllMessageTraceResults
2+
3+
Download the latest release: [Get-AllMessageTraceResults.ps1](https://github.com/microsoft/CSS-Exchange/releases/latest/download/Get-AllMessageTraceResults.ps1)
4+
5+
This script is a wrapper for the Exchange Online `Get-MessageTraceV2` cmdlet that automatically handles pagination. It requires an active Exchange Online PowerShell session. Results are collected in pages of up to 5000 and fetching continues until all results are returned or a timeout is reached.
6+
7+
## Parameters
8+
9+
-StartDate
10+
11+
The start date of the date range to search. Data is available for the last 90 days, with a maximum of 10 days per query.
12+
13+
-EndDate
14+
15+
The end date of the date range to search.
16+
17+
-SenderAddress
18+
19+
Filters results by the sender's email address. Accepts multiple values separated by commas.
20+
21+
-RecipientAddress
22+
23+
Filters results by the recipient's email address. Accepts multiple values separated by commas.
24+
25+
-MessageId
26+
27+
Filters results by the Message-ID header field of the message.
28+
29+
-MessageTraceId
30+
31+
Filters results by the message trace ID (GUID).
32+
33+
-FromIP
34+
35+
Filters results by the source IP address.
36+
37+
-ToIP
38+
39+
Filters results by the destination IP address.
40+
41+
-Status
42+
43+
Filters results by delivery status. Valid values are: `Delivered`, `Expanded`, `Failed`, `FilteredAsSpam`, `GettingStatus`, `Pending`, `Quarantined`.
44+
45+
-Subject
46+
47+
Filters results by the message subject. Use with `-SubjectFilterType` to control matching behavior.
48+
49+
-SubjectFilterType
50+
51+
Specifies how the `-Subject` value is evaluated. Valid values are: `Contains`, `StartsWith`, `EndsWith`.
52+
53+
-PageSize
54+
55+
The number of results to retrieve per page. Valid range is 1 to 5000. The default value is 5000.
56+
57+
-TimeoutMinutes
58+
59+
The number of minutes before the script stops fetching additional pages. The default value is 30 minutes.
60+
61+
## Examples
62+
63+
Retrieve all messages from the last 7 hours:
64+
65+
```powershell
66+
$messages = .\Get-AllMessageTraceResults.ps1 -StartDate (Get-Date).AddHours(-7) -EndDate (Get-Date)
67+
```
68+
69+
Filter by sender and status:
70+
71+
```powershell
72+
$messages = .\Get-AllMessageTraceResults.ps1 -StartDate (Get-Date).AddHours(-7) -EndDate (Get-Date) -SenderAddress "john@contoso.com" -Status "Delivered"
73+
```
74+
75+
Filter by recipient with a custom page size:
76+
77+
```powershell
78+
$messages = .\Get-AllMessageTraceResults.ps1 -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) -RecipientAddress "jane@contoso.com" -PageSize 1000
79+
```
80+
81+
## Output
82+
83+
Returns an array of message trace objects from `Get-MessageTraceV2`. The total number of retrieved messages is displayed upon completion.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ nav:
143143
- SetupLogReviewer: Setup/SetupLogReviewer.md
144144
- Transport:
145145
- Compute-TopExoRecipientsFromMessageTrace: Transport/Compute-TopExoRecipientsFromMessageTrace.md
146+
- Get-AllMessageTraceResults: Transport/Get-AllMessageTraceResults.md
146147
- ReplayQueueDatabases: Transport/ReplayQueueDatabases.md
147148
- Measure-EmailDelayInMTL: Transport/Measure-EmailDelayInMTL.md
148149
theme:

0 commit comments

Comments
 (0)