functions/Install-MDDaemon.ps1
function Install-MDDaemon { <# .SYNOPSIS Configures a computer for using the Mail Daemon .DESCRIPTION Configures a computer for using the Mail Daemon. This can include: - Installing the scheduled task - Creating folder and permission structure - Setting up the mail daemon configuration This action can be performed both locally or against remote computers .PARAMETER ComputerName The computer(s) to work against. Defaults to localhost, but can be used to install the module and set up the task across a wide range of computers. .PARAMETER Credential The credentials to use when connecting to computers. .PARAMETER NoTask Create the scheduled task. .PARAMETER TaskUser The credentials of the user the scheduled task will be executed as. .PARAMETER PickupPath The folder in which emails are queued for delivery. .PARAMETER SentPath The folder in which emails that were successfully sent are stored for a specified time before being deleted. .PARAMETER DaemonUser The user to grant permissions needed to function as the Daemon account. This grants read/write access to all working folders. .PARAMETER WriteUser The user/group to grant permissions to needed to queue email. This grants write-only access to the mail inbox. .PARAMETER MailSentRetention The time to keep successfully sent emails around. .PARAMETER SmtpServer The mailserver to use for sending emails. .PARAMETER SenderDefault The default email address to use as sender. This is used for mails queued by a task that did not specify a sender. .PARAMETER SenderCredential The credentials to use to send emails. Will be stored in an encrypted file that can only be opened by the taskuser and from the computer it is installed on. .PARAMETER RecipientDefault Default email address to send the email to, if the individual script queuing the email does not specify one. .EXAMPLE PS C:\> Install-MDDaemon -ComputerName DC1, DC2, DC3 -TaskUser $cred -DaemonUser "DOMAIN\MailDaemon" -SmtpServer 'mail.domain.org' -SenderDefault 'daemon@domain.org' -RecipientDefault 'helpdesk-t2@domain.org' Configures the mail daemon NoTask on the servers DC1, DC2 and DC3 #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [PSFComputer[]] $ComputerName = $env:COMPUTERNAME, [PSCredential] $Credential, [switch] $NoTask, [PSCredential] $TaskUser, [string] $PickupPath, [string] $SentPath, [string] $DaemonUser, [string[]] $WriteUser, [Timespan] $MailSentRetention, [string] $SmtpServer, [string] $SenderDefault, [PSCredential] $SenderCredential, [string] $RecipientDefault ) begin { #region Repetitions (ugly) # Specifying repetitions directly in the commandline is ugly. # It ignores explicit settings and requires copying the repetition object from another task. # Since we do not want to rely on another task being available, instead I chose to store an object in its XML form. # By deserializing this back into an object at runtime we can carry an object in scriptcode. $object = @' <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"> <Obj RefId="0"> <TN RefId="0"> <T>Microsoft.Management.Infrastructure.CimInstance#Root/Microsoft/Windows/TaskScheduler/MSFT_TaskRepetitionPattern</T> <T>Microsoft.Management.Infrastructure.CimInstance#MSFT_TaskRepetitionPattern</T> <T>Microsoft.Management.Infrastructure.CimInstance</T> <T>System.Object</T> </TN> <ToString>MSFT_TaskRepetitionPattern</ToString> <Props> <S N="Duration">P1D</S> <S N="Interval">PT30M</S> <B N="StopAtDurationEnd">false</B> <Nil N="PSComputerName" /> </Props> <MS> <Obj N="__ClassMetadata" RefId="1"> <TN RefId="1"> <T>System.Collections.ArrayList</T> <T>System.Object</T> </TN> <LST> <Obj RefId="2"> <MS> <S N="ClassName">MSFT_TaskRepetitionPattern</S> <S N="Namespace">Root/Microsoft/Windows/TaskScheduler</S> <S N="ServerName">C0020127</S> <I32 N="Hash">-1401671928</I32> <S N="MiXml"><CLASS NAME="MSFT_TaskRepetitionPattern"><PROPERTY NAME="Duration" TYPE="string"></PROPERTY><PROPERTY NAME="Interval" TYPE="string"></PROPERTY><PROPERTY NAME="StopAtDurationEnd" TYPE="boolean"></PROPERTY></CLASS></S> </MS> </Obj> </LST> </Obj> </MS> </Obj> </Objs> '@ $repetitionObject = [System.Management.Automation.PSSerializer]::Deserialize($object) #endregion Repetitions (ugly) #region Setup Task Configuration if (-not $NoTask) { $action = New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -Command Invoke-MDDaemon" $triggers = @() $triggers += New-ScheduledTaskTrigger -AtStartup -RandomDelay "00:15:00" $triggers += New-ScheduledTaskTrigger -At "00:00:00" -Daily if ($TaskUser) { $principal = New-ScheduledTaskPrincipal -UserId $TaskUser.UserName -LogonType Interactive } else { $principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType Interactive } $taskItem = New-ScheduledTask -Action $action -Principal $principal -Trigger $triggers -Description "Mail Daemon task, checks for emails to send at a specified interval. Uses the internal MailDaemon module." $taskItem.Author = Get-PSFConfigValue -FullName 'MailDaemon.Task.Author' -Fallback "$($env:USERDOMAIN) IT Department" $taskItem.Triggers[1].Repetition = $repetitionObject $parametersRegister = @{ TaskName = 'MailDaemon' InputObject = $taskItem } if ($TaskUser) { $parametersRegister["User"] = $TaskUser.UserName $parametersRegister["Password"] = $TaskUser.GetNetworkCredential().Password } } #endregion Setup Task Configuration #region Preparing Parameters $parameters = @{ } foreach ($key in $PSBoundParameters.Keys) { if ($key -notin 'PickupPath', 'SentPath', 'MailSentRetention', 'SmtpServer', 'SenderDefault', 'RecipientDefault') { continue } $parameters[$key] = $PSBoundParameters[$key] } $paramMainInstallCall = @{ ArgumentList = $parameters Credential = $Credential } #endregion Preparing Parameters #region The Main Setup Scriptblock $paramMainInstallCall["ScriptBlock"] = { param ( $Parameters ) Import-Module -Name PSFramework Import-Module -Name MailDaemon Set-MDDaemon @parameters #region Set file permissions if (-not (Test-Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailPickupPath'))) { $null = New-Item (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailPickupPath') -Force -ItemType Directory } if (-not (Test-Path (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath'))) { $null = New-Item (Get-PSFConfigValue -FullName 'MailDaemon.Daemon.MailSentPath') -Force -ItemType Directory } if ($Parameters.DaemonUser) { Update-MDFolderPermission -DaemonUser $Parameters.DaemonUser } if ($Parameters.WriteUser) { Update-MDFolderPermission -WriteUser $Parameters.WriteUser } #endregion Set file permissions } #endregion The Main Setup Scriptblock } process { #region Ensure Modules are installed $testResults = Test-Module -ComputerName $ComputerName -Credential $Credential -Module @{ MailDaemon = $script:ModuleVersion PSFramework = (Get-Module -Name PSFramework).Version } $failedTests = $testResults | Where-Object Success -EQ $false if ($failedTests) { $grouped = $failedTests | Group-Object Name foreach ($groupSet in $grouped) { Copy-Module -ModuleName (Get-Module $groupSet.Name).ModuleBase -ToComputer $groupSet.Group.ComputerName } } #endregion Ensure Modules are installed $paramMainInstallCall['ComputerName'] = $ComputerName Invoke-PSFCommand @paramMainInstallCall #region Securely store credentials if ($PSBoundParameters.ContainsKey('SenderCredential')) { $parametersSave = @{ ComputerName = $ComputerName Credential = $SenderCredential Path = 'C:\ProgramData\PowerShell\MailDaemon\senderCredentials.clixml' } if ($TaskUser) { $parametersSave['AccessAccount'] = $TaskUser } Save-MDCredential @parametersSave $parametersInvoke = @{ $parametersInvoke['ComputerName'] = $ComputerName } Invoke-PSFCommand @parametersInvoke -ScriptBlock { Set-MDDaemon -SenderCredentialPath "C:\ProgramData\PowerShell\MailDaemon\senderCredentials.clixml" } } #endregion Securely store credentials #region Setup Task if (-not $NoTask) { foreach ($computerObject in $ComputerName) { if ($ComputerName.Type -like 'CimSession') { $parametersRegister["CimSession"] = $computerObject.InputObject } elseif (-not $ComputerName.IsLocalhost) { $parametersRegister["CimSession"] = $ComputerName } $null = Register-ScheduledTask @parametersRegister } } #endregion Setup Task } } |