|
- param(
- [Parameter(Mandatory = $true)][int]$CampaignId,
- [string]$ConfigPath = (Join-Path (Split-Path -Parent $PSScriptRoot) 'config.ini'),
- [string]$OutputRoot
- )
- $ErrorActionPreference = 'Stop'
- . (Join-Path $PSScriptRoot 'campaign-common.ps1')
- if ($CampaignId -lt 1) { throw 'CampaignId must be positive' }
- $context = Get-MailContext $ConfigPath
- if (-not $OutputRoot) {
- $OutputRoot = if ($context.Settings['REPORT_DIR']) { $context.Settings['REPORT_DIR'] } else { 'reports' }
- }
- if (-not [System.IO.Path]::IsPathRooted($OutputRoot)) {
- $OutputRoot = Join-Path (Split-Path -Parent $ConfigPath) $OutputRoot
- }
- $OutputRoot = [System.IO.Path]::GetFullPath($OutputRoot)
- $null = New-Item -ItemType Directory -Path $OutputRoot -Force
- $db = Open-MailDatabase $context
- try {
- $command = New-DbCommand $db 'SELECT [Name] FROM [Campaign] WHERE [Id]=?'
- $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::Integer)
- $command.Parameters[0].Value = $CampaignId
- $name = $command.ExecuteScalar()
- if ($null -eq $name -or $name -is [DBNull]) { throw 'Campaign not found' }
- $suppression = @{}
- $command = New-DbCommand $db 'SELECT [EmailKey],[Reason] FROM [Suppression]'
- $reader = $command.ExecuteReader()
- try {
- while ($reader.Read()) { $suppression[[string]$reader.GetValue(0)] = [string]$reader.GetValue(1) }
- }
- finally { $reader.Dispose() }
- $deliveries = New-Object System.Collections.ArrayList
- $command = New-DbCommand $db 'SELECT [Id],[EmailKey],[Status],[AttemptCount],[LastAttemptAtUtc],[LastErrorCode] FROM [Delivery] WHERE [CampaignId]=? ORDER BY [Id]'
- $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::Integer)
- $command.Parameters[0].Value = $CampaignId
- $reader = $command.ExecuteReader()
- try {
- while ($reader.Read()) {
- $key = [string]$reader.GetValue(1)
- $at = if ($reader.IsDBNull(4)) { '' } else { ([DateTime]$reader.GetValue(4)).ToString('o') }
- $errorCode = if ($reader.IsDBNull(5)) { '' } else { [string]$reader.GetValue(5) }
- $reason = if ($suppression.ContainsKey($key)) { $suppression[$key] } else { '' }
- $null = $deliveries.Add([pscustomobject]@{
- CampaignId = $CampaignId; CampaignName = [string]$name;
- DeliveryId = [int]$reader.GetValue(0); Email = $key;
- Status = [string]$reader.GetValue(2); AttemptCount = [int]$reader.GetValue(3);
- LastAttemptUtc = $at; LastErrorCode = $errorCode; SuppressionReason = $reason
- })
- }
- }
- finally { $reader.Dispose() }
- $attempts = New-Object System.Collections.ArrayList
- $command = New-DbCommand $db 'SELECT a.[Id],a.[DeliveryId],a.[StartedAtUtc],a.[EndedAtUtc],a.[Outcome],a.[SanitizedError] FROM [Attempt] AS a INNER JOIN [Delivery] AS d ON a.[DeliveryId]=d.[Id] WHERE d.[CampaignId]=? ORDER BY a.[Id]'
- $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::Integer)
- $command.Parameters[0].Value = $CampaignId
- $reader = $command.ExecuteReader()
- try {
- while ($reader.Read()) {
- $started = if ($reader.IsDBNull(2)) { '' } else { ([DateTime]$reader.GetValue(2)).ToString('o') }
- $ended = if ($reader.IsDBNull(3)) { '' } else { ([DateTime]$reader.GetValue(3)).ToString('o') }
- $errorText = if ($reader.IsDBNull(5)) { '' } else { [string]$reader.GetValue(5) }
- $null = $attempts.Add([pscustomobject]@{
- CampaignId = $CampaignId; AttemptId = [int]$reader.GetValue(0);
- DeliveryId = [int]$reader.GetValue(1); StartedUtc = $started;
- EndedUtc = $ended; Outcome = [string]$reader.GetValue(4);
- SanitizedError = $errorText
- })
- }
- }
- finally { $reader.Dispose() }
- $stamp = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssZ') + '-' + [guid]::NewGuid().ToString('N').Substring(0,8)
- $prefix = Join-Path $OutputRoot "campaign-$CampaignId-$stamp"
- $deliveryPath = $prefix + '-deliveries.csv'
- $attemptPath = $prefix + '-attempts.csv'
- $deliveries | Export-Csv -LiteralPath $deliveryPath -NoTypeInformation -Encoding UTF8
- if ($attempts.Count) {
- $attempts | Export-Csv -LiteralPath $attemptPath -NoTypeInformation -Encoding UTF8
- }
- else {
- 'CampaignId,AttemptId,DeliveryId,StartedUtc,EndedUtc,Outcome,SanitizedError' |
- Set-Content -LiteralPath $attemptPath -Encoding UTF8
- }
- Write-Output "Delivery report: $deliveryPath"
- Write-Output "Attempt report: $attemptPath"
- }
- finally { $db.Dispose() }
|