param( [Parameter(Mandatory = $true)][int]$CampaignId, [string]$ConfigPath = (Join-Path (Split-Path -Parent $PSScriptRoot) 'config.ini'), [switch]$Send, [string]$PickupDirectory ) $ErrorActionPreference = 'Stop' . (Join-Path $PSScriptRoot 'dispatch-common.ps1') if ($CampaignId -lt 1) { throw 'CampaignId must be positive' } if ([bool]$Send -eq [bool]$PickupDirectory) { throw 'Choose exactly one mode: -Send or -PickupDirectory' } $context = Get-MailContext $ConfigPath $settings = $context.Settings if ($settings['SMTP_TLS'] -ne 'on' -or $settings['SMTP_STARTTLS'] -ne 'on') { throw 'SMTP_TLS and SMTP_STARTTLS must both be on' } $port = 0 if (-not [int]::TryParse($settings['SMTP_PORT'], [ref]$port) -or $port -lt 1 -or $port -gt 65535) { throw 'Invalid SMTP_PORT' } $testTo = [string]$settings['SMTP_TEST_TO'] $parsed = New-Object System.Net.Mail.MailAddress($testTo) if ($parsed.Address -ne $testTo) { throw 'SMTP_TEST_TO must be a single bare email address' } $db = Open-MailDatabase $context $client = $null $message = $null $password = $null try { $campaign = Get-ApprovedCampaignSnapshot $db $CampaignId $template = Get-TemplateSnapshot $db $campaign.TemplateId $html = Add-CampaignFooter $template.Document @{ From = $campaign.From; ReplyTo = $campaign.ReplyTo; Postal = $campaign.Postal } $message = New-Object System.Net.Mail.MailMessage $message.From = New-Object System.Net.Mail.MailAddress($campaign.From) $null = $message.ReplyToList.Add($campaign.ReplyTo) $null = $message.To.Add($testTo) $message.Subject = '[TEST] ' + $campaign.Subject $message.SubjectEncoding = [System.Text.Encoding]::UTF8 $view = [System.Net.Mail.AlternateView]::CreateAlternateViewFromString( $html, [System.Text.Encoding]::UTF8, 'text/html') foreach ($image in $template.Images) { $stream = New-Object System.IO.MemoryStream -ArgumentList (,([byte[]]$image.Bytes)) $resource = New-Object System.Net.Mail.LinkedResource($stream, $image.Type) $resource.ContentId = $image.Cid $resource.TransferEncoding = [System.Net.Mime.TransferEncoding]::Base64 $null = $view.LinkedResources.Add($resource) } $null = $message.AlternateViews.Add($view) $client = New-Object System.Net.Mail.SmtpClient($settings['SMTP_HOST'], $port) $client.Timeout = 20000 if ($Send) { $password = Load-SmtpPassword $context $client.UseDefaultCredentials = $false $client.Credentials = New-Object System.Net.NetworkCredential -ArgumentList @($settings['SMTP_USER'], $password) $client.EnableSsl = $true } else { if (-not (Test-Path -LiteralPath $PickupDirectory -PathType Container)) { throw 'Pickup directory does not exist' } $client.DeliveryMethod = [System.Net.Mail.SmtpDeliveryMethod]::SpecifiedPickupDirectory $client.PickupDirectoryLocation = [System.IO.Path]::GetFullPath($PickupDirectory) } $client.Send($message) Write-CampaignAudit $db 'approved_campaign_test_accepted' ([string]$CampaignId) ("Internal test to $testTo") Write-Output "Approved campaign $CampaignId test accepted for $testTo. Live delivery counts did not advance." } finally { if ($client) { $client.Dispose() } if ($message) { $message.Dispose() } if ($password) { $password.Dispose() } $db.Dispose() }