Public/Send-Email.ps1
Function Send-Email { <# .SYNOPSIS Sends an email using System.Net.Mail.SmtpClient. .DESCRIPTION This function sends an email to one or more recipients using the specified SMTP settings. It is designed to allow detailed control over mail sending parameters including CC and BCC. .PARAMETER Recipient The email address of the recipient. This parameter supports pipeline input. .PARAMETER Subject The subject of the email. .PARAMETER Body The body of the email, formatted as HTML. .PARAMETER From The sender's email address. Defaults to 'your.email@example.com'. .PARAMETER SmtpServer The SMTP server address. Defaults to 'smtp.example.com'. .PARAMETER SmtpPort The SMTP port to use. Defaults to 587. .PARAMETER Username The username for SMTP authentication. .PARAMETER Password The password for SMTP authentication. This should be provided securely. .PARAMETER Cc The CC recipients of the email. Multiple recipients can be provided as an array. .PARAMETER Bcc The BCC recipients of the email. Multiple recipients can be provided as an array. .PARAMETER Attachments A list of file paths for attachments. .PARAMETER UseSsl Specifies whether SSL should be used for the connection. Defaults to true. .EXAMPLE Send-Email -Recipient "primary@example.com" -Cc "other@example.com" -Bcc "hidden@example.com" -Subject "Quarterly Report" -Body "<h2>Please review the attached report.</h2>" -Username "user@example.com" -Password "password" -SmtpServer "smtp.example.com" -UseSsl $true .NOTES This function replaces the Send-MailMessage cmdlet with the more flexible .NET classes for sending emails. .NOTES Used Functions: Name | Module ---------------------------------------|-------------------------- Write-Verbose | Microsoft.PowerShell.Utility Write-Error | Microsoft.PowerShell.Utility New-Object | Microsoft.PowerShell.Utility Get-FunctionDisplay | EguibarIT.DelegationPS & EguibarIT.HousekeepingPS #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param ( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The email address of the recipient. This parameter supports pipeline input.', Position = 0)] [ValidateNotNullOrEmpty()] [ValidatePattern("^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$")] [Alias('To', 'EmailTo')] [string] $Recipient, [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The subject of the email.', Position = 1)] [ValidateNotNullOrEmpty()] [string] $Subject, [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The body of the email.', Position = 2)] [ValidateNotNullOrEmpty()] [string] $Body, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The senders email address', Position = 3)] [ValidatePattern("^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$")] [string] $From, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The SMTP server address.', Position = 4)] [string] $SmtpServer, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The SMTP port to use', Position = 5)] [PSDefaultValue(Help = 'Default SMTP port is: 587.')] [int] $SmtpPort = 587, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $true, HelpMessage = 'The username for SMTP authentication.', Position = 6)] [string] $Username, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $true, HelpMessage = 'The password for SMTP authentication. This should be provided securely as [System.Security.SecureString].', Position = 7)] [System.Security.SecureString] $Password, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The CC recipients of the email. Multiple recipients can be provided as an array.', Position = 8)] [ValidatePattern("^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$")] [string[]] $Cc, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The BCC recipients of the email. Multiple recipients can be provided as an array.', Position = 9)] [ValidatePattern("^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$")] [string[]] $Bcc, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'A list of file paths for attachments.', Position = 10)] [string[]] $Attachments, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Specifies whether SSL should be used for the connection. Defaults to true.', Position = 11)] [bool] $UseSsl ) Begin { $txt = ($Variables.HeaderHousekeeping -f (Get-Date).ToShortDateString(), $MyInvocation.Mycommand, (Get-FunctionDisplay -Hashtable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt ############################## # Variables Definition $mailMessage = [System.Net.Mail.MailMessage]::new() # Validate and prepare credentials #$smtpCreds = New-Object System.Net.NetworkCredential($Username, $securePassword) $smtpCreds = [System.Net.NetworkCredential]::New($Username, $securePassword) #$smtpClient = New-Object System.Net.Mail.SmtpClient($SmtpServer, $SmtpPort) $smtpClient = [System.Net.Mail.SmtpClient]::New() $smtpClient.EnableSsl = $UseSsl $smtpClient.UseDefaultCredentials = $false $smtpClient.DeliveryMethod = [System.Net.Mail.SmtpDeliveryMethod]::Network $smtpClient.TargetName = 'STARTTLS/smtp.gmail.com' $smtpClient.Credentials = $smtpCreds $smtpClient.Host = $SmtpServer $smtpClient.Port = $SmtpPort Write-Verbose -Message ('SMTP client configured with SSL={0}.' -f $UseSsl) } #end Begin Process { foreach ($rcpt in $Recipient) { $mailMessage.From = $From $mailMessage.To.Add($rcpt) $mailMessage.Subject = $Subject $mailMessage.Body = $Body $mailMessage.IsBodyHtml = $true if ($Cc) { foreach ($ccAddr in $Cc) { $mailMessage.CC.Add($ccAddr) } #end ForEach } #end If if ($Bcc) { foreach ($bccAddr in $Bcc) { $mailMessage.Bcc.Add($bccAddr) } #end ForEach } #end If # Handling attachments if ($Attachments) { foreach ($attachmentInput in $Attachments) { if (Test-Path $attachmentInput -PathType Leaf) { #$attachment = New-Object System.Net.Mail.Attachment($attachmentInput) $attachment = [System.Net.Mail.Attachment]::New($attachmentInput) $mailMessage.Attachments.Add($attachment) Write-Verbose 'Attached file: {0}' -f $attachmentInput } else { # Assume the input is plain text and create a MemoryStream attachment $stream = [System.IO.MemoryStream]::New() $writer = [System.IO.StreamWriter]::New($stream) $writer.Write($attachmentInput) $writer.Flush() $stream.Position = 0 $attachment = New-Object System.Net.Mail.Attachment($stream, 'Attachment.txt', 'text/plain') $mailMessage.Attachments.Add($attachment) Write-Verbose 'Attached text content as Attachment.txt' } #end If-Else } #end ForEach } #end If if ($PSCmdlet.ShouldProcess("$From to $rcpt", 'Send email')) { try { $smtpClient.Send($mailMessage) Write-Verbose -Message ('Email successfully sent to {0}; CC: {1}; BCC: {2}' -f $rcpt, $($Cc -join ', '), $($Bcc -join ', ')) } catch { Write-Error -Message ('Failed to send email to {0}: {1}' -f $rcpt, $_) } #end Try-Catch } #end If $mailMessage.Attachments.Dispose() $mailMessage.Dispose() } #end ForEach } #end Process End { $smtpClient.Dispose() $txt = ($Variables.FooterHousekeeping -f $MyInvocation.InvocationName, 'sending email.' ) Write-Verbose -Message $txt } #end End } |