thomminger
Goto Top

Powershell: Send a mime encrypted email with excel file attachment

Hi guys!

I've a tricky challenge.
I try to send mime encrypted mails.
Therefore I search in AD by using "cn" to get the certificate and mail address.
so far so good....

The native email without attachment run fine. email was sent encrypted:

$RecipientCN = $null
$RootDSE = $null
$Certificate = $null
$UserCertificate = $null
$ExcelFile = "C:\Temp\123.xlsx"

$RecipientCN='<cn>'
$SearchForestForPerson = New-Object DirectoryServices.DirectorySearcher([ADSI]"LDAP://DC=domain,DC=com")
$SearchForestForPerson.SearchScope = "subtree"
$SearchForestForPerson.PropertiesToLoad.Add("mail") | Out-Null
$SearchForestForPerson.PropertiesToLoad.Add("usercertificate") | Out-Null
$SearchForestForPerson.Filter = ("(&(objectClass=person)(CN=$RecipientCN))")
$Recipient = $SearchForestForPerson.FindOne()

$ChosenCertificate = $null
$Now = Get-Date
If ($Recipient.Properties.usercertificate -ne $null) {
ForEach ($UserCertificate in $Recipient.Properties.usercertificate) {
$ValidForSecureEmail = $false
$Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]$UserCertificate
$Extensions = $Certificate.Extensions
ForEach ($Extension in $Extensions) {
If ($Extension.EnhancedKeyUsages -ne $null) {
ForEach ($EnhancedKeyUsage in $Extension.EnhancedKeyUsages) {
If ($EnhancedKeyUsage.FriendlyName -ine "Secure Email") {
$ValidForSecureEmail = $true
break
}
}
If ($ValidForSecureEmail) {
break
}
}
}
If ($ValidForSecureEmail) {
If ($Now -gt $Certificate.NotBefore.AddMinutes(-5) -and $Now -lt $Certificate.NotAfter.AddMinutes(5)) {
$ChosenCertificate = $Certificate
}
}
If ($ChosenCertificate -ne $null) {
break

}
}
}


Add-Type -assemblyName "System.Security"
$MailClient = New-Object System.Net.Mail.SmtpClient "<smtp server>"
$Message = New-Object System.Net.Mail.MailMessage

$Message.To.Add($Recipient.properties.mail.item(0))
$Message.From = "<sender address>"
$Message.Subject = "Unencrypted subject of the message"
$Body = "This is the mail body"
$MIMEMessage = New-Object system.Text.StringBuilder
$MIMEMessage.AppendLine('Content-Type: text/plain; charset="UTF-8"') | Out-Null
$MIMEMessage.AppendLine('Content-Transfer-Encoding: 7bit') | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine($Body) | Out-Null

[Byte[]] $BodyBytes = [System.Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString())

$ContentInfo = New-Object System.Security.Cryptography.Pkcs.ContentInfo (,$BodyBytes)
$CMSRecipient = New-Object System.Security.Cryptography.Pkcs.CmsRecipient $ChosenCertificate
$EnvelopedCMS = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms $ContentInfo
$EnvelopedCMS.Encrypt($CMSRecipient)
[Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode()
$MemoryStream = New-Object System.IO.MemoryStream @(,$EncryptedBytes)
$AlternateView = New-Object System.Net.Mail.AlternateView($MemoryStream, "application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m")
$Message.AlternateViews.Add($AlternateView)
$MailClient.Send($Message)

...but I've no success with an encrypted email with attached excel file ($ExcelFile).

Do anyone have an idea or better a script code which I can use to send an encrypted email with an attachment?

Thanks!

Thomminger

Content-Key: 240989

Url: https://administrator.de/contentid/240989

Ausgedruckt am: 29.03.2024 um 12:03 Uhr

Mitglied: colinardo
colinardo 16.06.2014 aktualisiert um 17:00:14 Uhr
Goto Top
Hello Thomminger, welcome to administrator.de!
As far as i know, encrypted MIME attachments are not supported with System.Net.Mail. You may consider to implement your
own security mecanism (embed your mail as an encrypted attachment, ... like a scrambled *.zip file for example). Or use a third party programming-library for composing your messages.

A solution could be this library: http://www.codeproject.com/Articles/41727/An-S-MIME-Library-for-Sending ... which also supports attachments. You can compile this code an use the corresponding *.dll in your powershell-project by loading it via add-type.

Here is an example with this library and Powershell:

This sends an encrypted and signed message with an included attachment:
# load managed code library
add-type -Path "D:\Cpi.Net.SecureMail.dll"  

# load cryptocertificate by defining path and password
$mycert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("D:\yourcryptocert.p12","PASSWORD_OF_CERTIFICATE")  

# load recipient public certificate
$recipientCert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("D:\recipient.cer")  

# create secure mail message
$mail = new-object Cpi.Net.SecureMail.SecureMailMessage

# add sender and recipient
$mail.From = new-object Cpi.Net.SecureMail.SecureMailAddress("sender@domain.com","SENDERNAME",$mycert,$mycert)  
$mail.To.Add((new-object Cpi.Net.SecureMail.SecureMailAddress("recipient@domain.com","RECIPIENTNAME",$recipientCert)))  

$mail.Body = "This is a secure message with Attachment"  

# add secure attachment to mail message
$mail.Attachments.Add((new-object Cpi.Net.SecureMail.SecureAttachment("d:\yourattachment.txt")))  

# set mail properties (encrypted and signed)
$mail.IsSigned = $true
$mail.IsEncrypted = $true

# create smtp-client to send mail message
$smtp = new-object System.Net.Mail.SmtpClient("smtp.yourdomain.com", 25)  
$smtp.Credentials = new-object System.Net.NetworkCredential("SMTPUSERNAME","SMTPPASSWORD")  

# finally send mail
$smtp.Send($mail)
For simplicity i have compiled the library for you, download it here: Cpi.Net.SecureMail.dll (Compiled against .NET Framework 3.5)

Regards
@colinardo
Mitglied: Thomminger
Thomminger 16.06.2014 um 15:57:44 Uhr
Goto Top
Hi colinardo!

Thanks a lot for your fast reply!

As well for your support by creating and compiling this *.dll.

But...I hoped for a regular/standardized - in best case powershell or .net integrated solution.

Your provided solution with this compiled *.dll is not usable for my szenario. I've no doubt of your competence, but I've to fulfill different security standards and as you know - *.dll imply a lot of risks inside of them.

Thanks for your support. Maybe you or other wise guys in this community find additional solutions for this topic.

You're very welcome!

nice time!

regards
Thomminger
Mitglied: colinardo
colinardo 16.06.2014 aktualisiert um 17:12:50 Uhr
Goto Top
you can compile the dll out of the code yourself if you have security concerns... or look in the public available .net code of the library and implement this directly in powershell with the standard net objects... with that you can be sure there is nothing dangerous inside!