smtp.smime.lib.ps1
<#PSScriptInfo
.VERSION 1.0.4 .GUID b1f9432e-8253-441a-9fc1-d88cf2f17e8b .AUTHOR rob.kalmar .COMPANYNAME .COPYRIGHT Rob Kalmar .TAGS SMTP SMIME Email STARTTLS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Send encrypted and/or signed messages through SMTP. If you like this script please consider donating: https://bunq.me/robkalmar/5.00/PowerShellSMIMEToolkit Thanks! #> # PowerShell S/MIME Toolkit v1.0 # # # Copyright 2020 Rob Kalmar # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # Functions to send signed and encrypted s/mime messages # # Tested platforms: # Windows Server 2008 R2 (Needs this hotfix: http://support.microsoft.com/kb/2480994) # Windows Server 2012 # Windows Server 2012 R2 # Windows Server 2016 # Windows Server 2019 Function Show-License { [CmdletBinding()] param () Add-Type -AssemblyName System.Drawing Add-Type -AssemblyName System.Windows.Forms $Form1 = New-Object -TypeName System.Windows.Forms.Form $Form1.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (400,450) $Form1.Text = 'PowerShell S/MIME Toolkit v1.0 license' $Form1.StartPosition = 'CenterScreen' $Form1.FormBorderStyle = 'FixedDialog' $Form1.MaximizeBox = $false $Form1.MinimizeBox = $false $License = 'Copyright 2020 Rob Kalmar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.' $Label1 = New-Object -TypeName System.Windows.Forms.Label $Label1.Location = New-Object -TypeName System.Drawing.Size -ArgumentList (10,20) $Label1.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (380,280) $Label1.Text = $License $null = $Form1.Controls.Add($Label1) $Label2 = New-Object -TypeName System.Windows.Forms.Label $Label2.Location = New-Object -TypeName System.Drawing.Size -ArgumentList (10,320) $Label2.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (380,20) $Label2.Text = 'If you like these PowerShell scripts please feel free to make a donation...' $null = $Form1.Controls.Add($Label2) $LinkLabel1 = New-Object -TypeName System.Windows.Forms.LinkLabel $LinkLabel1.Location = New-Object -TypeName System.Drawing.Size -ArgumentList (10,340) $LinkLabel1.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (150,20) $LinkLabel1.LinkColor = 'BLUE' $LinkLabel1.ActiveLinkColor = 'RED' $LinkLabel1.Text = 'Make donation...' $null = $Form1.Controls.Add($LinkLabel1) $null = $LinkLabel1.Add_Click( { [Diagnostics.Process]::Start('https://bunq.me/robkalmar/5.00/PowerShellSMIMEToolkit') } ) $Label3 = New-Object -TypeName System.Windows.Forms.Label $Label3.Location = New-Object -TypeName System.Drawing.Size -ArgumentList (10,360) $Label3.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (380,20) $Label3.Text = 'Thank you!' $null = $Form1.Controls.Add($Label3) $Button1 = New-Object -TypeName System.Windows.Forms.Button $Button1.Location = New-Object -TypeName System.Drawing.Size -ArgumentList (290,380) $Button1.Size = New-Object -TypeName System.Drawing.Size -ArgumentList (80,20) $Button1.Text = 'Close' $null = $Form1.Controls.Add($Button1) $null = $Button1.Add_Click( { $Form1.Close() } ) $null = $Form1.ShowDialog() Return $null } Function Test-IsAscii { <# .SYNOPSIS Tests if the input string only contains ASCII values. .DESCRIPTION Tests if the input string only contains ASCII values. Returns true if this is the case, otherwise it returns false. .PARAMETER $text A string to check. .EXAMPLE Test-IsAscii -text 'This string contains only ASCII' #> param ( [parameter(Mandatory=$true)][string]$text ) [byte[]]$utf8text = [Text.Encoding]::UTF8.GetBytes($text) [string]$asciitext = [Text.Encoding]::ASCII.GetString($utf8text) If ($text -eq $asciitext) { Return $True } Else { Return $False } } function New-MailserverSettings { <# .SYNOPSIS Create a new PSObject which sets the properties of a mail server .DESCRIPTION This function creates a new PSObject and sets the properties of a mail server object. The function returns a PSObject. .EXAMPLE Call this function with a string representing the fully qualified domain name of the mail server New-MailserverSettings "mail.example.com" .PARAMETER $FQDN A string containing fully qualified domain name of the mail server .PARAMETER $Output An integer indicating whether to send to mail to the mail server and/or to disk. Output = 0 -> save to eml file Output = 1 -> send to smtp server Output = 2 -> save to eml file and send to smtp server .PARAMETER $Port A string containing the port of the mail server to connect to, default to "25" .PARAMETER $STARTTLS A boolean indicating whether to use STARTTLS or not when connecting to the mail server, defaults to $False .PARAMETER $Username A string containing the username used for authentication on the mail server, defaults to "" .PARAMETER $Password A secure string containing the password used for authentication on the mail server, defaults to 1 #> param ( [parameter(Mandatory=$true)][string]$FQDN, [ValidateSet(0,1,2)][int]$Output = 1, [string]$Port = '25', [string]$STARTTLS = $False, [string]$VerifyServerCertificate = $True, [string]$Username = '', [string]$Password = '' ) $MailServer = new-object -TypeName PSObject $MailServer | Add-Member -Name FQDN -Value $FQDN -MemberType NoteProperty $MailServer | Add-Member -Name Output -Value $Output -MemberType NoteProperty $MailServer | Add-Member -Name Port -Value $Port -MemberType NoteProperty $MailServer | Add-Member -Name STARTTLS -Value $STARTTLS -MemberType NoteProperty $MailServer | Add-Member -Name VerifyServerCertificate -Value $VerifyServerCertificate -MemberType NoteProperty $MailServer | Add-Member -Name Username -Value $Username -MemberType NoteProperty $MailServer | Add-Member -Name Password -Value $Password -MemberType NoteProperty Return $MailServer } function Get-MimeType { <# .SYNOPSIS Retrieves the Mime Type of a file extension from the Registry .DESCRIPTION This function retrieves the Mime Type of an file extension from the Windows Registry The function returns a string of the Mime Type. .EXAMPLE Call this function with a string representing the extension of a file Get-MimeType ".zip" .PARAMETER $Extension A string containing the extension of a file #> [CmdletBinding()] param ( [string]$Extension = $null ) $MimeType = 'application/octet-stream' $null = New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT Try { $Exists = Test-Path -Path "HKCR:$Extension" -ErrorAction Stop If ($Exists) { $Item = Get-ItemProperty -Path HKCR:$Extension -ErrorAction Stop $ItemContentType = $Item.'Content Type' If (($ItemContentType -eq $null) -or ($ItemContentType -eq '')) { $ItemContentType = 'application/octet-stream' } $MimeType = $ItemContentType } } Catch { $MimeType = 'application/octet-stream' } Return $MimeType } function New-UTF8EncodedFileName { <# .SYNOPSIS Given a filename string the function encodes it into UTF8. .DESCRIPTION Given a filename string the function encodes it into UTF8 for use in the Content-Type or Content-Disposition name/filename paramters .PARAMETER $FileName The filename to encode into UTF8 .EXAMPLE New-UTF8EncodedFileName -FileName 'example.txt' Encodes the filename example.txt to UTF8. #> param ( [parameter(Mandatory=$true)][string]$FileName ) [String]$Header = ' =?UTF-8?B?' [String]$Footer = '?=' [String]$EncodedB64FileName = $null [int]$ChunkSize = 60 #needs to be multiple of 4, otherwise Outlook does not like it. [String]$B64FileName = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($FileName)) [int]$SizeB64FileName = $B64FileName.Length $UTF8EncodedFileName = New-Object -TypeName System.Text.StringBuilder [int]$Position = 0 While ($Position -le ($SizeB64FileName - $ChunkSize)) { $null = $UTF8EncodedFileName.AppendLine() $EncodedB64FileName = $Header + $B64FileName.Substring($Position,$ChunkSize) + $Footer $null = $UTF8EncodedFileName.Append("$EncodedB64FileName") $Position = $Position + $ChunkSize } If (($SizeB64FileName-$Position) -gt 0) { $null = $UTF8EncodedFileName.AppendLine() $EncodedB64FileName = $Header + $B64FileName.Substring($Position,$SizeB64FileName-$Position) + $Footer $null = $UTF8EncodedFileName.Append("$EncodedB64FileName") } Return $UTF8EncodedFileName } function New-HeaderMimePart { <# .SYNOPSIS Creates a new header for a Mime part .DESCRIPTION This function creates a new header for Mime part of a message The function returns a string .EXAMPLE Call this function with a string representing the Mime Type and file name of the Mime part to which the header will be added New-HeaderMimePart "application/octet-stream" "filename.zip" .PARAMETER $MimeType A string containing the Mime Type of a file .PARAMETER $MimeType A string containing the file name of a file #> param ( [parameter(Mandatory=$true)][string]$MimeType, [parameter(Mandatory=$true)][string]$FileName ) $MimePartHeader = New-Object -TypeName System.Text.StringBuilder If ((Test-IsAscii -text $FileName) -and ($FileName.Length -le 64)) { $null = $MimePartHeader.AppendLine("Content-Type: $MimeType; charset=`"utf-8`";") $null = $MimePartHeader.AppendLine(" name=`"$FileName`"") $null = $MimePartHeader.AppendLine('Content-Transfer-Encoding: base64') $null = $MimePartHeader.AppendLine('Content-Disposition: attachment;') $null = $MimePartHeader.AppendLine(" filename=`"$FileName`"") $null = $MimePartHeader.AppendLine() } Else { [String]$UTF8EncodedFileName = New-UTF8EncodedFileName -FileName $FileName $null = $MimePartHeader.Append("Content-Type: $MimeType; charset=`"utf-8`"; name=`"") $null = $MimePartHeader.Append("$UTF8EncodedFileName") $null = $MimePartHeader.AppendLine('"') $null = $MimePartHeader.AppendLine('Content-Transfer-Encoding: base64') $null = $MimePartHeader.Append('Content-Disposition: attachment; filename="') $null = $MimePartHeader.Append("$UTF8EncodedFileName") $null = $MimePartHeader.AppendLine('"') $null = $MimePartHeader.AppendLine() } Return $MimePartHeader } function New-MimePart { <# .SYNOPSIS Creates a new Mime part for a Mime Message .DESCRIPTION This function creates a new Mime part for a Mime message The function returns a string .EXAMPLE Call this function with an object representing a file New-MimePart file .PARAMETER $File An object representing a file #> param ( [parameter(Mandatory=$true)][IO.FileInfo]$File ) $Extension = $null $Extension = [IO.Path]::GetExtension($File) $MimeType = Get-MimeType -Extension $Extension $FileName = [IO.Path]::GetFileName($File) $Header = New-HeaderMimePart -MimeType $MimeType -FileName $FileName $MimePart = New-Object -TypeName System.Text.StringBuilder $null = $MimePart.Append($Header) [Byte[]] $BinaryData = [IO.File]::ReadAllBytes($File) [string] $Base64Value = [Convert]::ToBase64String($BinaryData, [Base64FormattingOptions]::InsertLineBreaks) $null = $MimePart.Append($Base64Value) $null = $MimePart.AppendLine() Return $MimePart } function New-MimeMessage { <# .SYNOPSIS Create a Mime Message .DESCRIPTION This function creates multipart/mixed a Mime message The function returns a string .EXAMPLE Call this function with a string representing the body of the Mime Message and an object representing a file New-MimeMessage "body text" file .PARAMETER $File An string representing the body text of the message .PARAMETER $File An object representing a file #> [CmdletBinding()] param ( [string]$Body = $null, [IO.FileInfo[]]$FileList = $null ) $MIMEMessage = New-Object -TypeName System.Text.StringBuilder If ($FileList -eq $null) { $null = $MIMEMessage.AppendLine("Content-Type: text/plain; charset=`"utf-8`"") $null = $MIMEMessage.AppendLine('Content-Transfer-Encoding: base64') $null = $MIMEMessage.AppendLine() [Byte[]] $BodyBytes = [Text.Encoding]::UTF8.GetBytes($Body) [string] $BodyB64 = [Convert]::ToBase64String($BodyBytes, [Base64FormattingOptions]::InsertLineBreaks) $null = $MIMEMessage.Append($BodyB64) $null = $MIMEMessage.AppendLine() } Else { [String]$Boundary = 'boundary-' + [guid]::NewGuid() $null = $MIMEMessage.AppendLine('Content-Type: multipart/mixed;') $null = $MIMEMessage.AppendLine(" boundary=$Boundary") $null = $MIMEMessage.AppendLine() $null = $MIMEMessage.AppendLine('This is a multi-part message in MIME format.') $null = $MIMEMessage.AppendLine("--$Boundary") $null = $MIMEMessage.AppendLine("Content-Type: text/plain; charset=`"utf-8`"") $null = $MIMEMessage.AppendLine('Content-Transfer-Encoding: base64') $null = $MIMEMessage.AppendLine() [Byte[]] $BodyBytes = [Text.Encoding]::UTF8.GetBytes($Body) [string] $BodyB64 = [Convert]::ToBase64String($BodyBytes, [Base64FormattingOptions]::InsertLineBreaks) $null = $MIMEMessage.Append($BodyB64) $null = $MIMEMessage.AppendLine() $null = $MIMEMessage.Append("--$Boundary") $File = $null Foreach ($File in $FileList) { $null = $MIMEMessage.AppendLine() $Part = New-MimePart -File $File $null = $MIMEMessage.Append($Part) $null = $MIMEMessage.Append("--$Boundary") } $null = $MIMEMessage.AppendLine('--') } Return $MIMEMessage } function New-EncryptedContent { <# .SYNOPSIS Returns an encrypted byte array of a string using given certificate .DESCRIPTION This function encrypts a given string using the public key of a given certificate. The function returns an array of encrypted bytes. .EXAMPLE Call this function with a string to be encrypted and a certificate containing a public key New-EncryptedContent "Example string" certificate .PARAMETER $MIMEMessage A string containing the message to be encrypted .PARAMETER $Certificate A certificate which will be used to encrypt the Mime Message. .PARAMETER $EncryptionAlgorithm A string specifying the encryption algorithm to be used for encyption, defaults to "1.2.840.113549.3.7" (3DES) "1.2.840.113549.3.2" # RC2 Key length 40/64/128 "1.3.14.3.2.7" #DES "1.2.840.113549.3.7" #3DES "2.16.840.1.101.3.4.1.2" #AES-128 "2.16.840.1.101.3.4.1.22" #AES-192 "2.16.840.1.101.3.4.1.42" #AES-256 .PARAMETER $KeyLength An integer specifying the key length to be used in case of using RC2, defaults to 128 Valid values are [40,64,128] #> param ( [parameter(Mandatory=$true)][string]$MIMEMessage, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, [string]$EncryptionAlgorithm = '1.2.840.113549.3.7', [ValidateSet(40,64,128)][int]$KeyLength = 128 ) Add-Type -AssemblyName System.Security [Byte[]] $BodyBytes = [Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString()) $ContentInfo = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$BodyBytes) $SubjectIdentifierType = 2 $AlgorithmIdentifier = New-Object -TypeName System.Security.Cryptography.Pkcs.AlgorithmIdentifier -ArgumentList $EncryptionAlgorithm If ($EncryptionAlgorithm -eq '1.2.840.113549.3.2') { $AlgorithmIdentifier.KeyLength = $KeyLength } $EnvelopedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.EnvelopedCms -ArgumentList $SubjectIdentifierType , $ContentInfo , $AlgorithmIdentifier $CMSRecipient = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsRecipient -ArgumentList $SubjectIdentifierType , $Certificate $EnvelopedCMS.Encrypt($CMSRecipient) [Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode() Return $EncryptedBytes } function New-SignedContent { <# .SYNOPSIS Returns a signed byte array of a string using given certificate .DESCRIPTION This function signs a given string using the private key of a given certificate. The function returns an array of signed bytes. .EXAMPLE Call this function with a string to be signed and a certificate containing a private key New-SignedContent "Example string" certificate .PARAMETER $MIMEMessage A string containing the message to be signed .PARAMETER $Certificate A certificate which will be used to sign the Mime Message. .PARAMETER $EndCertOnly Set to $True to avoid issues with building up the certificate chain to the root certificate, defaults to $False .PARAMETER $Detached If set to $True the signatue will be detached so non smime capable clients can still read the message. .PARAMETER $Boundary Defines the boudary used in the multipart MIME message. .PARAMETER $DigestAlgorithm A string specifying which digest algorithm to use, defaults to "1.3.14.3.2.26" (SHA-1) "1.2.840.113549.2.5" #md5 "1.3.14.3.2.26" #SHA-1 "2.16.840.1.101.3.4.2.1" #SHA-256 "2.16.840.1.101.3.4.2.2" #SHA-384 "2.16.840.1.101.3.4.2.3" #SHA-512 .PARAMETER $EnhancedProtection Turn ON or OFF enhanced protection. When ON the recipient and subject will be added as signed attributes to the signature. This enables you to check if they were changed in transit. Note: No mail client actually checks for this, so you need to program something yourself. .PARAMETER $Recipient The recipient the include as a signed attribute. .PARAMETER $Subject The subject to include as a signed attribute. #> param ( [parameter(Mandatory=$true)][string]$MIMEMessage, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, [bool]$EndCertOnly = $False, [bool]$Detached = $True, [string]$Boundary = 'boundary-1', [string]$DigestAlgorithm = '1.3.14.3.2.26', [bool]$EnhancedProtection = $True, [string]$Recipient = $null, [string]$Subject = $null ) Add-Type -AssemblyName System.Security [Byte[]] $BodyBytes = [Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString()) $ContentInfo = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$BodyBytes) $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $ContentInfo, $Detached $CMSSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate If ($EndCertOnly) { $CMSSigner.IncludeOption = [Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly } Else { $CMSSigner.IncludeOption = [Security.Cryptography.X509Certificates.X509IncludeOption]::WholeChain } $CMSSigner.DigestAlgorithm = $DigestAlgorithm $TimeStamp=Get-Date $Pkcs9SigningTime = New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime -ArgumentList ($TimeStamp) $null = $CMSSigner.SignedAttributes.Add($Pkcs9SigningTime) If ($EnhancedProtection) { If ($Recipient) { $documentNameAttribute = New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9DocumentName -ArgumentList ("$Recipient") $null = $CMSSigner.SignedAttributes.Add($documentNameAttribute) } If ($Subject) { $documentDescriptionAttribute = New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9DocumentDescription -ArgumentList ("$Subject") $null = $CMSSigner.SignedAttributes.Add($documentDescriptionAttribute) } } $SignedCMS.ComputeSignature($CMSSigner) [Byte[]] $SignedBytes = $SignedCMS.Encode() If ($Detached -eq $True) { $MultipartSigned = New-Object -TypeName System.Text.StringBuilder $null = $MultipartSigned.AppendLine("--$Boundary") $null = $MultipartSigned.AppendLine("$MIMEMessage") $null = $MultipartSigned.AppendLine("--$Boundary") $null = $MultipartSigned.AppendLine('Content-Type: application/pkcs7-signature; name="smime.p7s"') $null = $MultipartSigned.AppendLine('Content-Disposition: attachment; filename="smime.p7s"') $null = $MultipartSigned.AppendLine('Content-Transfer-Encoding: base64') $null = $MultipartSigned.AppendLine() [String]$Signature = [Convert]::ToBase64String($SignedBytes, [Base64FormattingOptions]::InsertLineBreaks) $null = $MultipartSigned.AppendLine("$Signature") $null = $MultipartSigned.AppendLine() $null = $MultipartSigned.AppendLine("--$Boundary--") [Byte[]] $SignedBytes = [Text.Encoding]::UTF8.GetBytes($MultipartSigned.ToString()) } Return $SignedBytes } function Send-SMIMEMail { <# .SYNOPSIS Sends a SMIME message to a mail server .DESCRIPTION This function sends message to a mail server The function returns $True if the message is successfully sent otherwise $False .EXAMPLE Call this function with an object representing a mail server and an object of type System.Net.Mail.MailMessage Send-SMIMEMail mailserver message .PARAMETER $MailServer An object representing a mail server .PARAMETER $File An object representing an object of type System.Net.Mail.MailMessage #> param ( [parameter(Mandatory=$true)][PSObject]$MailServer, [parameter(Mandatory=$true)][Net.Mail.MailMessage]$Message ) $SendMail = $False $scriptPath = $(Split-Path -Path $script:MyInvocation.MyCommand.Path) $MailClient = New-Object -TypeName System.Net.Mail.SmtpClient -ArgumentList $MailServer.FQDN, $MailServer.Port $MailClient.Credentials = New-Object -TypeName System.Net.NetworkCredential -ArgumentList ($MailServer.Username, $MailServer.Password) $Delivery = $MailServer.Output switch ($Delivery) { 1 { $MailClient.DeliveryMethod = [Net.Mail.SmtpDeliveryMethod]::Network $MailClient.EnableSsl = [Convert]::ToBoolean($($MailServer.STARTTLS)) If ([Convert]::ToBoolean($($MailServer.VerifyServerCertificate))) { [Net.ServicePointManager]::ServerCertificateValidationCallback = $null } Else { [Net.ServicePointManager]::ServerCertificateValidationCallback = { Return $True } } Try { $MailClient.Send($Message) $MailClient.Dispose() $SendMail = $True } Catch { $SendMail = $False $MailClient.Dispose() } } 2 { $MailClient.DeliveryMethod = [Net.Mail.SmtpDeliveryMethod]::SpecifiedPickupDirectory $Exists = Test-Path -Path "$scriptPath\sent" if (!$Exists) { $null = New-Item -ItemType directory -Path "$scriptPath\sent" } $MailClient.PickupDirectoryLocation = "$scriptPath\sent" Try { $MailClient.Send($Message) $SendMail = $True } Catch { $SendMail = $False } $MailClient.DeliveryMethod = [Net.Mail.SmtpDeliveryMethod]::Network $MailClient.EnableSsl = [Convert]::ToBoolean($($MailServer.STARTTLS)) If ([Convert]::ToBoolean($($MailServer.VerifyServerCertificate))) { [Net.ServicePointManager]::ServerCertificateValidationCallback = $null } Else { [Net.ServicePointManager]::ServerCertificateValidationCallback = { Return $True } } Try { $MailClient.Send($Message) $MailClient.Dispose() $SendMail = $True } Catch { $SendMail = $False $MailClient.Dispose() } } Default { $MailClient.DeliveryMethod = [Net.Mail.SmtpDeliveryMethod]::SpecifiedPickupDirectory $Exists = Test-Path -Path "$scriptPath\sent" if (!$Exists) { $null = New-Item -ItemType directory -Path "$scriptPath\sent" } $MailClient.PickupDirectoryLocation = "$scriptPath\sent" Try { $MailClient.Send($Message) $MailClient.Dispose() $SendMail = $True } Catch { $SendMail = $False $MailClient.Dispose() } } } Return $SendMail } function Get-Oid { <# .SYNOPSIS Get the Oid of an Encryption or Digest algorithm. .DESCRIPTION This function return the Oid (as string) for a given encryption or digest algorithm (or $null when not known). .PARAMETER Algorithm A string of the name of the encryption or digest algorithm. .EXAMPLE Get-Oid -Algorithm 'aes128' This returns a string with the Oid of aes128 which is '2.16.840.1.101.3.4.1.2' #> param ( [parameter(Mandatory=$true)][string]$Algorithm ) Switch ($Algorithm) { # DigestAlgorithms 'md5' { $Oid = '1.2.840.113549.2.5' } 'sha1' { $Oid = '1.3.14.3.2.26' } 'sha256' { $Oid = '2.16.840.1.101.3.4.2.1' } 'sha384' { $Oid = '2.16.840.1.101.3.4.2.2' } 'sha512' { $Oid = '2.16.840.1.101.3.4.2.3' } # EncryptionAlgorithms 'rc2' { $Oid = '1.2.840.113549.3.2' } 'des' { $Oid = '1.3.14.3.2.7' } '3des' { $Oid = '1.2.840.113549.3.7' } 'aes128' { $Oid = '2.16.840.1.101.3.4.1.2' } 'aes192' { $Oid = '2.16.840.1.101.3.4.1.22' } 'aes256' { $Oid = '2.16.840.1.101.3.4.1.42' } # Unknown Default { $Oid = $null } } Return $Oid } Function New-MicAlg { <# .SYNOPSIS Given a digest algorithm returns a string for use in the micalg parameter in the Content-Type. .DESCRIPTION Given a digest algorithm returns a string for use in the micalg parameter in the Content-Type. This uses the specs of smime 3.1 (https://tools.ietf.org/html/rfc3851#section-3.4.3.2) If you want to use smime 3.2 see RFC 5751 .PARAMETER $DigestAlgorithm The Digest Algorithm used for signing messages. .EXAMPLE New-MicAlg -DigestAlgorithm '1.3.14.3.2.26' Returns sha1 #> param ( [parameter(Mandatory=$true)][string]$DigestAlgorithm ) switch ($DigestAlgorithm) { '1.2.840.113549.2.5' { $MicAlg = 'md5'} '1.3.14.3.2.26' { $MicAlg = 'sha1'} '2.16.840.1.101.3.4.2.1' { $MicAlg = 'sha256'} '2.16.840.1.101.3.4.2.2' { $MicAlg = 'sha384'} '2.16.840.1.101.3.4.2.3' { $MicAlg = 'sha512'} Default { $MicAlg = 'sha1'} } Return $MicAlg } function Send-EncryptedMail { <# .SYNOPSIS Send an encrypted mail message through a mail server .DESCRIPTION This function sends an encrypted message through a mail server using a specified certificate. The function returns $True when successfull otherwise $False .EXAMPLE Call this function with a mail server object, a certificate of the recipient, a string containing the sender mail address, a string with the subject text, a string containing the body text, an attachment representing a file. Send-EncryptedMail mailserver certificate "example@example.com" "subject text" "body text" file .PARAMETER $MailServer An object representing a mail server .PARAMETER $RecipientCertificate A certificate which will be used to encrypt the body text and attachment. .PARAMETER $Sender A string representing an e-mail address .PARAMETER $Subject A string representing the subject of a mail message .PARAMETER $Body A string representing the body text of a mail message .PARAMETER $Attachment An object representing an array of files. .PARAMETER $EncryptionAlgorithm A string specifying the encryption algorithm to be used for encyption, defaults to "1.2.840.113549.3.7" (3DES) "1.2.840.113549.3.2" # RC2 Key length 40/64/128 "1.3.14.3.2.7" #DES "1.2.840.113549.3.7" #3DES "2.16.840.1.101.3.4.1.2" #AES-128 "2.16.840.1.101.3.4.1.22" #AES-192 "2.16.840.1.101.3.4.1.42" #AES-256 .PARAMETER $KeyLength An integer specifying the key length to be used in case of using RC2, defaults to 128 Valid values are [40,64,128] #> param ( [parameter(Mandatory=$true)][PSObject]$MailServer, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$RecipientCertificate, [parameter(Mandatory=$true)][string]$Sender, [string]$Subject = $null, [string]$Body = $null, [IO.FileInfo[]]$Attachments = $null, [string]$EncryptionAlgorithm = '3des', [ValidateSet(40,64,128)][int]$KeyLength = 128 ) $EncryptionAlgorithm = Get-Oid -Algorithm $EncryptionAlgorithm $SendEncryptedMail = $False $MIMEMessage = New-MimeMessage -Body $Body -FileList $Attachments $EncryptedBytes = New-EncryptedContent -MIMEMessage $MIMEMessage -Certificate $RecipientCertificate -EncryptionAlgorithm $EncryptionAlgorithm -KeyLength $KeyLength $MemoryStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(,$EncryptedBytes) $ContentType = New-Object -TypeName System.Net.Mime.ContentType -ArgumentList 'application/pkcs7-mime; name="smime.p7m"; smime-type=enveloped-data' $AlternateView = New-Object -TypeName System.Net.Mail.AlternateView -ArgumentList ($MemoryStream, $ContentType) $Recipient = $RecipientCertificate.GetNameInfo('EmailName', $False) $Message = New-Object -TypeName System.Net.Mail.MailMessage $Message.To.Add($Recipient) $Message.From = $Sender $Message.SubjectEncoding = [Text.Encoding]::UTF8 $Message.Subject = $Subject $Message.Headers.Add('Return-Path', "<$Sender>") $Message.Headers.Add('X-Secured-By','Powershell S/MIME Toolkit v1.0') $Message.AlternateViews.Add($AlternateView) $SendEncryptedMail = Send-SMIMEMail -MailServer $MailServer -Message $Message Return $SendEncryptedMail } function Send-SignedMail { <# .SYNOPSIS Send an encrypted mail message through a mail server .DESCRIPTION This function sends an encrypted message through a mail server using a specified certificate. The function returns $True when successfull otherwise $False .EXAMPLE Call this function with a mail server object, a certificate of the recipient, a string containing the sender mail address, a string with the subject text, a string containing the body text, an attachment representing a file. Send-EncryptedMail mailserver certificate "example@example.com" "subject text" "body text" file .PARAMETER $MailServer An object representing a mail server .PARAMETER $Recipient A string representing an e-mail address .PARAMETER $SenderCertificate A certificate which will be used to sign the body text and attachment. .PARAMETER $Subject A string representing the subject of a mail message .PARAMETER $Body A string representing the body text of a mail message .PARAMETER $Attachment An object representing an array of files. .PARAMETER $EndCertOnly Set to $True to avoid issues with building up the certificate chain to the root certificate, defaults to $False .PARAMETER $Detached If set to $True the signatue will be detached so non smime capable clients can still read the message. .PARAMETER $DigestAlgorithm A string specifying which digest algorithm to use, defaults to "1.3.14.3.2.26" (SHA-1) "1.2.840.113549.2.5" #md5 "1.3.14.3.2.26" #SHA-1 "2.16.840.1.101.3.4.2.1" #SHA-256 "2.16.840.1.101.3.4.2.2" #SHA-384 "2.16.840.1.101.3.4.2.3" #SHA-512 .PARAMETER $EnhancedProtection Turn ON or OFF enhanced protection. When ON the recipient and subject will be added as signed attributes to the signature. #> param ( [parameter(Mandatory=$true)][PSObject]$MailServer, [parameter(Mandatory=$true)][string]$Recipient, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$SenderCertificate, [string]$Subject = $null, [string]$Body = $null, [IO.FileInfo[]]$Attachments = $null, [bool]$EndCertOnly = $False, [bool]$Detached = $True, [string]$DigestAlgorithm = 'sha1', [bool]$EnhancedProtection = $True ) $DigestAlgorithm = Get-Oid -Algorithm $DigestAlgorithm $SendSignedMail = $False [String]$Boundary = 'boundary-2-' + [guid]::NewGuid() $MIMEMessage = New-MimeMessage -Body $Body -FileList $Attachments $SignedBytes = New-SignedContent -MIMEMessage $MIMEMessage -Certificate $SenderCertificate -EndCertOnly $EndCertOnly -Detached $Detached -Boundary $Boundary -DigestAlgorithm $DigestAlgorithm -EnhancedProtection $EnhancedProtection -Recipient $Recipient -Subject $Subject $MemoryStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(,$SignedBytes) If ($Detached -eq $True) { $MicAlg = New-MicAlg -DigestAlgorithm $DigestAlgorithm $ContentType = New-Object -TypeName System.Net.Mime.ContentType -ArgumentList "multipart/signed; boundary=`"$Boundary`"; protocol=`"application/pkcs7-signature`"; micalg=$MicAlg" } Else { $ContentType = New-Object -TypeName System.Net.Mime.ContentType -ArgumentList 'application/pkcs7-mime; smime-type=signed-data; name="smime.p7m"' } $AlternateView = New-Object -TypeName System.Net.Mail.AlternateView -ArgumentList ($MemoryStream, $ContentType) If ($Detached -eq $True) { $AlternateView.TransferEncoding = '2' } Else { $AlternateView.TransferEncoding = '1' } $Sender = $SenderCertificate.GetNameInfo('EmailName', $False) $Message = New-Object -TypeName System.Net.Mail.MailMessage $Message.To.Add("<$Recipient>") $Message.From = "<$Sender>" $Message.SubjectEncoding = [Text.Encoding]::UTF8 $Message.Subject = $Subject $Message.Headers.Add('Return-Path', "<$Sender>") $Message.Headers.Add('X-Secured-By','Powershell S/MIME Toolkit v1.0') $Message.AlternateViews.Add($AlternateView) $SendSignedMail = Send-SMIMEMail -MailServer $MailServer -Message $Message Return $SendSignedMail } function Send-SignedAndEncryptedMail { <# .SYNOPSIS Send a signed and encrypted mail message through a mail server .DESCRIPTION This function sends an encrypted message through a mail server using a specified certificate. The function returns $True when successfull otherwise $False .EXAMPLE Call this function with a mail server object, a certificate of the recipient, a certificate of the sender, a string with the subject text, a string containing the body text, an attachment representing a file. Send-SignedAndEncryptedMail mailserver certificate certificate "subject text" "body text" file .PARAMETER $MailServer An object representing a mail server .PARAMETER $RecipientCertificate A certificate which will be used to encrypt the body text and attachment. .PARAMETER $SenderCertificate A certificate which will be used to sign the body text and attachment. .PARAMETER $Subject A string representing the subject of a mail message .PARAMETER $Body A string representing the body text of a mail message .PARAMETER $Attachment An object representing an array of files. .PARAMETER $EndCertOnly Set to $True to avoid issues with building up the certificate chain to the root certificate, defaults to $False .PARAMETER $Detached If set to $True the signatue will be detached so non smime capable clients can still read the message. .PARAMETER $DigestAlgorithm A string specifying which digest algorithm to use, defaults to "1.3.14.3.2.26" (SHA-1) "1.2.840.113549.2.5" #md5 "1.3.14.3.2.26" #SHA-1 "2.16.840.1.101.3.4.2.1" #SHA-256 "2.16.840.1.101.3.4.2.2" #SHA-384 "2.16.840.1.101.3.4.2.3" #SHA-512 .PARAMETER $EncryptionAlgorithm A string specifying the encryption algorithm to be used for encyption, defaults to "1.2.840.113549.3.7" (3DES) "1.2.840.113549.3.2" # RC2 Key length 40/64/128 "1.3.14.3.2.7" #DES "1.2.840.113549.3.7" #3DES "2.16.840.1.101.3.4.1.2" #AES-128 "2.16.840.1.101.3.4.1.22" #AES-192 "2.16.840.1.101.3.4.1.42" #AES-256 .PARAMETER $KeyLength An integer specifying the key length to be used in case of using RC2 , defaults to 128 Valid values are [40,64,128] .PARAMETER $EnhancedProtection Turn ON or OFF enhanced protection. When ON the recipient and subject will be added as signed attributes to the signature. #> param ( [parameter(Mandatory=$true)][PSObject]$MailServer, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$RecipientCertificate, [parameter(Mandatory=$true)][Security.Cryptography.X509Certificates.X509Certificate2]$SenderCertificate, [string]$Subject = $null, [string]$Body = $null, [IO.FileInfo[]]$Attachments = $null, [bool]$EndCertOnly = $False, [bool]$Detached = $True, [string]$DigestAlgorithm = 'sha1', [string]$EncryptionAlgorithm = '3des', [ValidateSet(40,64,128)][int]$KeyLength = 128, [bool]$EnhancedProtection = $True ) $DigestAlgorithm = Get-Oid -Algorithm $DigestAlgorithm $EncryptionAlgorithm = Get-Oid -Algorithm $EncryptionAlgorithm $SendSignedAndEncryptedMail = $False [String]$Boundary = 'boundary-2-' + [guid]::NewGuid() $Recipient = $RecipientCertificate.GetNameInfo('EmailName', $False) $MIMEMessage = New-MimeMessage -Body $Body -FileList $Attachments $SignedBytes = New-SignedContent -MIMEMessage $MIMEMessage -Certificate $SenderCertificate -EndCertOnly $EndCertOnly -Detached $Detached -Boundary $Boundary -DigestAlgorithm $DigestAlgorithm -EnhancedProtection $EnhancedProtection -Recipient $Recipient -Subject $Subject $SignedB64String = [Convert]::ToBase64String($SignedBytes, [Base64FormattingOptions]::InsertLineBreaks) $MIMESigned = New-Object -TypeName system.Text.StringBuilder If ($Detached -eq $True) { $null = $MIMESigned.AppendLine('Content-Type: multipart/signed;') $null = $MIMESigned.AppendLine(" boundary=`"$Boundary`";") $MicAlg = New-MicAlg -DigestAlgorithm $DigestAlgorithm $null = $MIMESigned.AppendLine(" protocol=`"application/pkcs7-signature`"; micalg=$MicAlg") $null = $MIMESigned.AppendLine('Content-Transfer-Encoding: 7bit') $null = $MIMESigned.AppendLine() $Body = [Text.Encoding]::ASCII.GetString($SignedBytes) $null = $MIMESigned.Append("$Body") $null = $MIMESigned.AppendLine() } Else { $null = $MIMESigned.AppendLine('Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type=signed-data') $null = $MIMESigned.AppendLine('Content-Transfer-Encoding: base64') $null = $MIMESigned.AppendLine('Content-Disposition: attachment; filename="smime.p7m"') $null = $MIMESigned.AppendLine() $null = $MIMESigned.Append($SignedB64String) $null = $MIMESigned.AppendLine() } $EncryptedBytes = New-EncryptedContent -MIMEMessage $MIMESigned -Certificate $RecipientCertificate -EncryptionAlgorithm $EncryptionAlgorithm -KeyLength $KeyLength $MemoryStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(,$EncryptedBytes) $ContentType = New-Object -TypeName System.Net.Mime.ContentType -ArgumentList 'application/pkcs7-mime; name="smime.p7m"; smime-type=enveloped-data' $AlternateView = New-Object -TypeName System.Net.Mail.AlternateView -ArgumentList ($MemoryStream, $ContentType) $Sender = $SenderCertificate.GetNameInfo('EmailName', $False) $Message = New-Object -TypeName System.Net.Mail.MailMessage $Message.To.Add($Recipient) $Message.From = $Sender $Message.SubjectEncoding = [Text.Encoding]::UTF8 $Message.Subject = $Subject $Message.Headers.Add('Return-Path', "<$Sender>") $Message.Headers.Add('Content-Disposition', 'attachment; filename="smime.p7m"') $Message.Headers.Add('X-Secured-By','Powershell S/MIME Toolkit v1.0') $Message.AlternateViews.Add($AlternateView) $SendSignedAndEncryptedMail = Send-SMIMEMail -MailServer $MailServer -Message $Message Return $SendSignedAndEncryptedMail } # example # show license $null = Show-License # enter your SMTP servername or IP address: $FQDN = '<server>' # enter the port to connect to (defaults: 25): $Port = '25' # use STARTTLS to switch to TLS/SSL connection: $STARTTLS = $True # should the server certificate be validated: $VerifyServerCertificate = $True # enter the username to authenticatie with: $Username = '<username>' # enter the password used to authenticate: $Password = '<pasword>' # use 0 for testing # Output = 0 -> save to eml file # Output = 1 -> send to smtp server # Output = 2 -> save to eml file and send to smtp server $Output = 0 # create a new MailServerSettings object: $MailServerDetails = New-MailServerSettings -FQDN $FQDN -Output $Output -Port $Port -STARTTLS $STARTTLS -VerifyServerCertificate $VerifyServerCertificate -Username $Username -Password $Password # select the certificate used for the sender (used for signing messages): # normally you would use: # $CertSenderFile = "$(Split-Path -Path $script:MyInvocation.MyCommand.Path)\certificates\personone.pfx" # $CertSenderPassword = 'password' # $CertSender = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList ($CertSenderFile, $CertSenderPassword) # # in this example we use this: $CertSenderBase64 = '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 TFVFQk9YLmlwdjZ4cy5ubF9Sb290LVNlY3VyZS1DQSgxKS5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6 Ly9ibHVlYm94LmlwdjZ4cy5ubC9vY3NwMEUGA1UdEQQ+MDygJAYKKwYBBAGCNxQCA6AWDBRwZXJz b24ub25lQGlwdjZ4cy5ubIEUcGVyc29uLm9uZUBpcHY2eHMubmwwDQYJKoZIhvcNAQELBQADggIB AENF8WBDzyNY6ttp0JgFzriqVJNIvSM0qzrmH2hXlEni4wEJ5n0S7ct1KdtiHlREDbSyWzDQ7Js3 IhtwJ4DVZ8lEKzeSaZ44V39Da/0Gaq2+SikdqE68+fDsl+gf50Wys62jhBktNDpOvQ9p6At7gGDj NvaXrWzkhvL61b3gNem25DABrHHVbvKtiHoX2EonYjtMGtq2R3evb3XN00KZ9qcSV9gwryGjyQcv rJe80YgN7MXi2OnBs4no8YJjqjNQc1lMWJC0XONM2k7oy+9vyJg/FJvBd2fTzQeQJCZte1NAlP3y i91JbNWrDXMqeKpYOZTQR+ifcjED+YlVRsTQwaLXC2SPNAIxpVK0ohq4PwYffYMl6zfs5iDI7eUZ 8xRw/41UfR9Ex1wmHZc2kjz7taqKxzO5r2wvHbDsBychVdtqDoTFtLpvhi9//QRzCWxnOA+pLsz0 94ZbVPbYIFjhlm8/7b0aqhBeK9RfWIt2RUF11QyikwgNlnEVxnkAbNbuZv5lLPbDUrSq28Odrj+/ hscGQAcmOaenGPvvV1+3CVz/tygxr6GqA2NNdtn82y0IYusSUeo3Unmzqn9QZ/GRASR1XjGD011k 5cqPRACZMzb4ew418Jy6sDhVWWJqGA+TeXw88pnrdKy0MPpzYE3MS63+GMSmJ1FbmVHyFSP/Aywt MYIBFjATBgkqhkiG9w0BCRUxBgQEAQAAADAyBgorBgEEAYI3EQNHMSQEIm8AdgBoAGIAbwB4AC4A aQBwAHYANgB4AHMALgBuAGwAAAAwgcoGCisGAQQBgjcRA1cxgbsEgbgAAAAAAAAAAAIAAAAAAAAA AgAAAGwAZABhAHAAOgAAAHsARQA0ADkANwA2ADQAQwAzAC0ANgAxADcAMQAtADQAOQAzADQALQBB ADkAMQA4AC0ANQA1ADMAMgA5AEYAQgA3ADAANAA4ADkAfQAAAEIATABVAEUAQgBPAFgALgBpAHAA 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' $CertSenderBytes = [Convert]::FromBase64String($CertSenderBase64) $CertSenderPassword = 'password' $CertSender = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList ($CertSenderBytes, $CertSenderPassword) # get the From address from the certificate $fromAddress = $CertSender.GetNameInfo('EmailName', $False) # select the certificate used for the recipient (used for encrypting messages): # normally you would use: # $CertRecipientFile = "$(Split-Path -Path $script:MyInvocation.MyCommand.Path)\certificates\persontwo.cer" # $CertRecipient = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $CertRecipientFile # # in this example we use this: $CertRecipientBase64 = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlHdVRDQ0JLR2dBd0lCQWdJS0pIcTM2QUFC QUFBQmRqQU5CZ2txaGtpRzl3MEJBUXNGQURCRk1SSXdFQVlLDQpDWkltaVpQeUxHUUJHUllDYm13 eEZqQVVCZ29Ka2lhSmsvSXNaQUVaRmdacGNIWTJlSE14RnpBVkJnTlZCQU1UDQpEbEp2YjNRdFUy VmpkWEpsTFVOQk1CNFhEVEl3TURNeE9URXpOVEl6TmxvWERUTXdNRE14TnpFek5USXpObG93DQpn WW94RWpBUUJnb0praWFKay9Jc1pBRVpGZ0p1YkRFV01CUUdDZ21TSm9tVDhpeGtBUmtXQm1sd2Rq WjRjekVQDQpNQTBHQTFVRUN4TUdhWEIyTm5oek1SRXdEd1lEVlFRTEV3aGxlSFJsY201aGJERVRN QkVHQTFVRUF4TUtVR1Z5DQpjMjl1SUZSM2J6RWpNQ0VHQ1NxR1NJYjNEUUVKQVJZVWNHVnljMjl1 TG5SM2IwQnBjSFkyZUhNdWJtd3dnZ0VpDQpNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dF S0FvSUJBUURQYVo5TGZ2VEhIUWVUUnpDa1BxNitqdkoyDQpnd2REQ1FwWm5JY05sRG5IeFhRblJS R296VE5sNVlNa01nMkJTNm11TjFZOU5la3FYSGVFUkNobEVyUkxCUWFWDQpjVE1jWllxVVRWM3FF MFY3UWVtNkkrM210MGozTXlNczJqTElSZy9NOTMrWW9jVTlNV1l4a0JRdmJuY0Y1L3BjDQplbUdw Qm0rS1VlVVNsNDlCbDFQTmhQSG50bm1WbDA0R0FMd2w5bWtHMU8ydC8wTURrcnZ2RG9yN3k4QXhB ano3DQpwenZ1T0UrSkZLTjJISS91SFJ3NmNxemZ1UjB3WFpUZ3Y1Y0FlSUwySU1xQWlkUHVxeWdS TE1tbVFsd2dUY1BqDQpZTXlNbHFJUnE0eExUQUJRYk9sMEZHci9Bb0xFbXVodVFhRFozV3lNM3Yr T2pqeVltTmQ4K3dzUlhYWHpBZ01CDQpBQUdqZ2dKak1JSUNYekErQmdrckJnRUVBWUkzRlFjRU1U QXZCaWNyQmdFRUFZSTNGUWlCcjVZY2hxM3VNb1NCDQptUldDajVrN2d2UDdQNEY0Z3V2T0M0SG5q QzBDQVdRQ0FRTXdLUVlEVlIwbEJDSXdJQVlJS3dZQkJRVUhBd0lHDQpDQ3NHQVFVRkJ3TUVCZ29y QmdFRUFZSTNDZ01FTUE0R0ExVWREd0VCL3dRRUF3SUZvREExQmdrckJnRUVBWUkzDQpGUW9FS0RB bU1Bb0dDQ3NHQVFVRkJ3TUNNQW9HQ0NzR0FRVUZCd01FTUF3R0Npc0dBUVFCZ2pjS0F3UXdSQVlK DQpLb1pJaHZjTkFRa1BCRGN3TlRBT0JnZ3Foa2lHOXcwREFnSUNBSUF3RGdZSUtvWklodmNOQXdR Q0FnQ0FNQWNHDQpCU3NPQXdJSE1Bb0dDQ3FHU0liM0RRTUhNQjBHQTFVZERnUVdCQlRJenZpYkVR dTRScVlVVE5qK0ozRFo4SEtkDQpiakFmQmdOVkhTTUVHREFXZ0JUaFk2V2MvbVVBZlJCWEcyYkZO K29kVG9rQTN6QkhCZ05WSFI4RVFEQStNRHlnDQpPcUE0aGpab2RIUndPaTh2WW14MVpXSnZlQzVw Y0hZMmVITXVibXd2UTJWeWRFVnVjbTlzYkM5U2IyOTBMVk5sDQpZM1Z5WlMxRFFTNWpjbXd3Z1pR R0NDc0dBUVVGQndFQkJJR0hNSUdFTUZjR0NDc0dBUVVGQnpBQ2hrdG9kSFJ3DQpPaTh2WW14MVpX SnZlQzVwY0hZMmVITXVibXd2UTJWeWRFVnVjbTlzYkM5Q1RGVkZRazlZTG1sd2RqWjRjeTV1DQpi RjlTYjI5MExWTmxZM1Z5WlMxRFFTZ3hLUzVqY25Rd0tRWUlLd1lCQlFVSE1BR0dIV2gwZEhBNkx5 OWliSFZsDQpZbTk0TG1sd2RqWjRjeTV1YkM5dlkzTndNRVVHQTFVZEVRUStNRHlnSkFZS0t3WUJC QUdDTnhRQ0E2QVdEQlJ3DQpaWEp6YjI0dWRIZHZRR2x3ZGpaNGN5NXViSUVVY0dWeWMyOXVMblIz YjBCcGNIWTJlSE11Ym13d0RRWUpLb1pJDQpodmNOQVFFTEJRQURnZ0lCQURTRnRndHNqamdSRm5q SGJCam1GV3ErRE94a0dkZWt4bTJRdjhsRHJZbFRERWgxDQpBSEVoZ2Y0dkJNMTVhbUFPaGZIS3d6 TlA4dURZSmU2ejg2dzE0ZHhub3AxMEVnaGVWODhnS1I4ZE9YQk9WTmpODQpJTDVQbHNjVUh6N3JS OWQ3UkJLZ2g1K0VpODRGUElReU1UUW9mMVIzUlJPV1l4anBvSWErbTRrWXFQNWs0K3JVDQpaeFFK NGE1QUhJSE5OWDU3cXltbkorbkZOSDZFMUxFbzh1am01bnQzUFB1STFzMm9PNTZVMk5tYllwV1pB YnNkDQpXOGJEaWxPcHhkK0RwNzJsTTliYndZSVQzSW9EdzVTcXFIcFBBZS90SENxNjh6OE8wUzZx cFBmVUo4eW1GU0NaDQpYYWhQZCtNc1JMMnJaUXYzQlA2QUd1eDFhL0tUcDZwano5cEE0VmlSMzZi YmJFbi8yWnNPeVdxS1hNbE9sWXlsDQo4dGJiaXh3RnpZOVFmRjI2Q2l0a3BxcURmUzB5Yk11UWJW NnZyTVY5blNFaGwvN3RWYmNXZkEyeTdtK0ZPTHc5DQo5eHRTVCtjb2FjVjQzek5WYWp6L2dMWGNR ZDk1eXhaTk5wTGVGYzEzMHJlcUxESXhLUm4vWFBxMmUwZWJpQW8vDQpyTFI3TnowbThqMitKbnVs V2RmajEyV1l4ZFl5azJTdGVMTVVaTDlSSWxJRzNxUTNndUNTeWI3bk1GQUhtV0pODQpEVDF5VTFB Y3JVVmtBRng2Z1c0eStMR1FlWkw0TjNhSFJoMWovQ1J0bEF2bUJvK01zMTRhSFEyRks1NGxpVWUw DQp4eFVSSmg2Ry9paDNldUR3dHN5SWo3M2oxYlJzM1FVV3dZTmdtekx1K21QeGdPa0FSZFZpODlB SzFtejgNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg== ' $CertRecipientBytes = [Convert]::FromBase64String($CertRecipientBase64) $CertRecipient = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList ($CertRecipientBytes, $null) # get the To address from the certificate $toAddress = $CertRecipient.GetNameInfo('EmailName', $False) # security settings: # should the signed message be detached (readable for non s/mime clients): $Detached = $True # encryption algorithm to be used: # valid values are: 'rc2','des','3des','aes128','aes192','aes256' $EncryptionAlgorithm = 'aes256' # when using encryption algorith 'rc2' you can specify a key length: # valid values are: 40, 64, 128 $KeyLength = 128 # signing algorithm to be used: # valid values are: 'md5','sha1','sha256','sha384','sha512' $DigestAlgorithm = 'sha256' # should the whole certificate chain be verified for the signing certificate: # set this to $True if you do not have the root certificate (and/or intermediate certificates) of the signing certificate installed. $EndCertOnly = $True # if you want to use enhanced protection for signing the message: # this adds signed attributes to the signed part # it adds the recipient address to Pkcs9DocumentName # and adds the subject to Pkcs9DocumentDescription # this has no effect on most mail reader programs $EnhancedProtection = $True # the text of the body: $Bodytext = "This is the body of the mail message. ©`r`nBye...`r`n" # attchments you want to include: # you can use wildcard to select multiple attachment # set to $null if you do not want to include attachments # normally you can use: # $Attachments = get-item -Path "$(Split-Path -Path $script:MyInvocation.MyCommand.Path)\attachments\*" # # in this example we do not include attachments $Attachments = $null # set the subject and send using encryption and signing: $Subject = '© Signed and encrypted ©' $Result = Send-SignedAndEncryptedMail -MailServer $mailserverdetails -RecipientCertificate $certrecipient -SenderCertificate $certsender -Subject $subject -Body $bodytext -EncryptionAlgorithm $EncryptionAlgorithm -KeyLength $KeyLength -DigestAlgorithm $DigestAlgorithm -EndCertOnly $EndCertOnly -Detached $Detached -Attachments $attachments -EnhancedProtection $EnhancedProtection $Result # set the subject and send using encryption only: $Subject = '© Encrypted ©' $Result = Send-EncryptedMail -MailServer $mailserverdetails -RecipientCertificate $certrecipient -Sender $fromAddress -Subject $subject -Body $bodytext -EncryptionAlgorithm $EncryptionAlgorithm -KeyLength $KeyLength -Attachments $attachments $Result # set the subject and send using signing only: $Subject = '© Signed ©' $Result = Send-SignedMail -MailServer $mailserverdetails -Recipient $toAddress -SenderCertificate $certsender -Subject $subject -Body $bodytext -DigestAlgorithm $DigestAlgorithm -EndCertOnly $EndCertOnly -Detached $Detached -Attachments $attachments -EnhancedProtection $EnhancedProtection $Result |