functions/Invoke-MDDaemon.ps1
|
function Invoke-MDDaemon { <# .SYNOPSIS Processes the email queue and sends emails .DESCRIPTION Processes the email queue and sends emails. Should be scheduled using a scheduled task. Recommended Setting: - Launch on boot with delay - Launch on Midnight - Repeat every 30 minutes for one day .PARAMETER NoLogging Disables Eventlog logging. By default, the mail invocation is logged to the Windows Eventlog. .EXAMPLE PS C:\> Invoke-MDDaemon Processes the email queue and sends emails #> [CmdletBinding()] param ( [switch] $NoLogging ) begin { if (-not (Test-Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailPickupPath'))) { $null = New-Item -Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailPickupPath') -ItemType Directory } if (-not (Test-Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath'))) { $null = New-Item -Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath') -ItemType Directory } $failedPath = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailFailedPath' $abandonThreshold = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailAbandonThreshold' if (-not (Test-Path $failedPath)) { $null = New-Item -Path $failedPath -ItemType Directory } if (-not $NoLogging -and ($PSVersionTable.PSVersion.Major -lt 6 -or $IsWindows)) { Set-PSFLoggingProvider -Name eventlog -InstanceName MailDaemonInvoke -LogName MailDaemon -Source MailDaemon -Enabled $true -Wait } } process { trap { Disable-PSFLoggingProvider -Name eventlog -InstanceName MailDaemonInvoke throw $_ } #region Send mails foreach ($item in (Get-ChildItem -Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailPickupPath') -Filter "*.clixml")) { $email = Import-Clixml -Path $item.FullName # Skip emails that should not yet be processed if ($email.NotBefore -gt (Get-Date)) { continue } # Build email parameters $parameters = @{ SmtpServer = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.SmtpServer' Encoding = ([System.Text.Encoding]::UTF8) ErrorAction = 'Stop' } if (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.UseSSL' -Fallback $false) { $parameters['UseSSL'] = $true } if ($email.To) { $parameters["To"] = $email.To } else { $parameters["To"] = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.RecipientDefault' } if ($email.From) { $parameters["From"] = $email.From } else { $parameters["From"] = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.SenderDefault' } if ($email.Cc) { $parameters["Cc"] = $email.Cc } if ($email.Bcc) { $parameters["Bcc"] = $email.Bcc } if ($email.Subject) { $parameters["Subject"] = $email.Subject } else { $parameters["Subject"] = "<no subject>" } if ($email.Priority) { $parameters["Priority"] = $email.Priority } if ($email.Body) { $parameters["Body"] = $email.Body } if ($null -ne $email.BodyAsHtml) { $parameters["BodyAsHtml"] = $email.BodyAsHtml } if ($email.Attachments) { if ($email.AttachmentsBinary) { $tempAttachmentParentDir = New-Item (Join-Path $item.Directory $item.BaseName) -Force -ItemType Directory $attachmentCounter = 0 $parameters["Attachments"] = @() # Using multiple subfolders to allow for duplicate attachment names foreach ($binaryAttachment in $email.AttachmentsBinary) { $tempAttachmentDir = New-Item (Join-Path $tempAttachmentParentDir $attachmentCounter) -Force -ItemType Directory $tempAttachmentPath = Join-Path $tempAttachmentDir $binaryAttachment.Name $null = [System.IO.File]::WriteAllBytes($tempAttachmentPath, $binaryAttachment.Data) $parameters["Attachments"] = @($parameters["Attachments"]) + $tempAttachmentPath $attachmentCounter = $attachmentCounter + 1 } } else { $parameters["Attachments"] = $email.Attachments } } if (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.SenderCredentialPath') { $parameters["Credential"] = Import-Clixml -Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.SenderCredentialPath') } Write-PSFMessage -Level Verbose -String 'Invoke-MDDaemon.SendMail.Start' -StringValues @($email.Taskname, $parameters['Subject'], $parameters['From'], ($parameters['To'] -join ",")) -Target $email.Taskname try { Send-MailMessage @parameters } catch { "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff') : $_" | Set-PSFFileContent -Path ($item.FullName -replace '.clixml', '.txt') -Append #region Abandon Email if beyond threshold if ($item.CreationTime.Add($abandonThreshold) -lt (Get-Date)) { Write-PSFMessage -String 'Invoke-MDDaemon.SendMail.Abandon' -StringValues $email.Taskname, $abandonThreshold $item.LastWriteTime = Get-Date Move-Item -LiteralPath $item.FullName -Destination $failedPath Move-Item -LiteralPath ($item.FullName -replace '.clixml', '.txt') -Destination $failedPath if ($email.Attachments -and $email.RemoveAttachments) { foreach ($attachment in $email.Attachments) { Remove-Item $attachment -Force } } } #endregion Abandon Email if beyond threshold Stop-PSFFunction -String 'Invoke-MDDaemon.SendMail.Failed' -StringValues $email.Taskname -ErrorRecord $_ -Continue -Target $email.Taskname } Write-PSFMessage -Level Verbose -String 'Invoke-MDDaemon.SendMail.Success' -StringValues $email.Taskname -Target $email.Taskname # Remove attachments only if ordered and mail was sent successfully if ($email.Attachments -and $email.RemoveAttachments) { foreach ($attachment in $email.Attachments) { Remove-Item $attachment -Force } } # Remove temp deserialized attachments if used if ($email.AttachmentsBinary) { $null = Remove-Item -Path $tempAttachmentParentDir -Recurse -Force } # Update the timestamp (the timeout for deletion uses this) and move it to the sent items folder $item.LastWriteTime = Get-Date try { Move-Item -Path $item.FullName -Destination (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath') -Force -ErrorAction Stop } catch { Write-PSFMessage -Level Warning -String 'Invoke-MDDaemon.ManageSuccessJob.Failed' -StringValues $email.Taskname -Target $email.Taskname } } #endregion Send mails Disable-PSFLoggingProvider -Name eventlog -InstanceName MailDaemonInvoke } end { #region Cleanup expired mails $sentRetention = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentRetention' foreach ($item in (Get-ChildItem -Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath'))) { if ($item.LastWriteTime.Add($sentRetention) -lt (Get-Date)) { Remove-Item $item.FullName } } $failedRetention = Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailFailedRetention' foreach ($item in (Get-ChildItem -Path $failedPath)) { if ($item.LastWriteTime.Add($failedRetention) -lt (Get-Date)) { Remove-Item $item.FullName } } #endregion Cleanup expired mails } } |