Mailozaurr icon indicating copy to clipboard operation
Mailozaurr copied to clipboard

Feature Request: Signed mail

Open jschpp opened this issue 5 years ago • 15 comments

Hi there.

I love this collection of utilities and replaced some of my own tools with it. Would it be possible to add S/MIME signed mails to the Send-Email function?

Also on this topic: The System.Net.Mail.SmtpClient API is obsolete. Microsoft recommends using https://github.com/jstedfast/MimeKit

jschpp avatar Jul 19 '19 12:07 jschpp

Hi,

I know it's a bit obsolete however it's the only way that works and allows you to define EmailReplyTo. Send-MailMessage doesn't allow you to do that.

Does MimeKit allow you to do that?

I was thinking to move Send-Email to Emailimo, and as soon as most of my modules move to Emailimo (if I will be able to migrate them) scrap some Email functions out.

PrzemyslawKlys avatar Jul 19 '19 12:07 PrzemyslawKlys

Yeah. Send-MailMessage can't do signing either.

MimeKit can do pretty much everything. I've looked for ReplyTo specifically and there seems to be options for that. The documentation seems very comprehensive http://www.mimekit.net/docs/html/Creating-Messages.htm It looks like you could cast System.Net.Mail.MailMessage to MimeKit.MimeMessage as well.

You would need to pack MimeKit with Emailimo though.

jschpp avatar Jul 19 '19 13:07 jschpp

Also. After looking over System.Net.Mail.SmtpClient it looks like signing mails is non trivial... So if you don't want to migrate to MimeKit right now I can understand if this takes a while

jschpp avatar Jul 19 '19 13:07 jschpp

Well, I did take a look and it's not trivial. Most likely would require a separate module to cover all topics related to MimeKit. But let's keep this open. Maybe when I'll get time, or I'll be bored I'll take a look and implement something. If not signing then maybe migrate to mimekit to be 'supported'.

PrzemyslawKlys avatar Jul 19 '19 16:07 PrzemyslawKlys

I've found an Implementation of MailKit which handles closely to Send-MailMessage PSMailKit

As of now it's not on the gallery. I've opened an issue https://github.com/dbaileyut/PSMailKit/issues/7 to this end.

jschpp avatar Jul 23 '19 06:07 jschpp

I've done my own implementation of MailKit in https://github.com/EvotecIT/Mailozaurr

It doesn't yet have signing but I'm one step closer :-)

PrzemyslawKlys avatar Jun 19 '20 13:06 PrzemyslawKlys

I've done my own implementation of MailKit in https://github.com/EvotecIT/Mailozaurr

It doesn't yet have signing but I'm one step closer :-)

It looks quite good. I'm going to have a closer look next week :-)

jschpp avatar Jun 20 '20 10:06 jschpp

I am liking the Mailozaurr module so far but would like to +1 for the Signed mail. (Things like password expiry notifications would be great to be sent signed)

DaveyRance avatar Jan 19 '21 21:01 DaveyRance

I agree. It would be cool. Resources:

  • https://stackoverflow.com/questions/30983883/sign-and-encrypt-on-mimekit
  • http://www.mimekit.net/docs/html/Working-With-SMime.htm

No promises - but when I'll get some free time I'll take a look.

PrzemyslawKlys avatar Jan 20 '21 20:01 PrzemyslawKlys

I had a few looks at SMIME functionality. The main problem as I see it is that we (the module) need to curate a database for certificate management.

Per default this would be a SQLite DB.

Shall we simply use SQLite or should there be a class which can be inherited from for Users/Admins to write their own implementation of SMIMEContext? Also there seems to be a WindowsDefaultContext which seems to access the windows certificate store. How should that one be provided?

The actual signing implementation itself is not that much work as soon as you have a context.

Here is an example with the windows default context:

index 5ed86b8..775f6db 100644
--- a/Public/Send-EmailMessage.ps1
+++ b/Public/Send-EmailMessage.ps1
@@ -530,6 +530,10 @@
     }
     $Message.Body = $BodyBuilder.ToMessageBody()

+    $ctx = $ctx = [MimeKit.Cryptography.WindowsSecureMimeContext]::new([System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser)
+    $Signer = $Message.From.Mailboxes[0].Clone()
+    $Message.Body = [MimeKit.Cryptography.MultipartSigned]::Create($ctx, $Signer, [MimeKit.Cryptography.DigestAlgorithm]::Sha256, $Message.Body)
+
     ### SMTP Part Below
     $SmtpClient = [MySmtpClient]::new()
     if ($SkipCertificateRevocation) {

A few notes here

  • The use of [0].clone() to get the signer was needed since I can't figure out how to tell PS that $Message.From.Mailboxes should be an IEnumerable so I couldn't use FirstOrDefault() as shown in the documentation
  • The Windows Context will propt you for a password if you saved your key with strong security

jschpp avatar Oct 27 '21 09:10 jschpp

As you can see I also tried the SMIME in the Testing-Certs branch but a bit failed attempt.

https://github.com/EvotecIT/Mailozaurr/blob/884faf3093166e50fff51c50285d7b8935c2557e/Public/Send-EmailMessage.ps1#L542

I saw windosecuremimecontext, but what about linux/macos. I am not sure what is the best approach. I would like it to be as portable as possible.

PrzemyslawKlys avatar Oct 27 '21 12:10 PrzemyslawKlys

I saw windosecuremimecontext, but what about linux/macos. I am not sure what is the best approach. I would like it to be as portable as possible.

In that case I'd say you should bundle System.Data.SQLite for Windows Systems and it should be possible to use that in concert with Mono.Data.Sqlite on Non Windows Systems.

The question then is where you want to store the SQLite DB per default.

Maybe I'll take a look at writing a Context this weekend

jschpp avatar Oct 29 '21 13:10 jschpp

Once you have something ready and working the path can be then decided. Let's work out the working solution.

I guess we should have something hardcoded if parameter is not provided, but also allow people to define location where the db is located, or maybe explicitly prompt for it - since it can be hard to define on macos/linux/winows to make sure all 3 locations are supported

PrzemyslawKlys avatar Oct 29 '21 14:10 PrzemyslawKlys

Proposed path

[Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)
[Environment]::GetFolderPath([Environment+SpecialFolder]::CommonApplicationData)

On windows:

image

On linux: image

PrzemyslawKlys avatar Oct 29 '21 14:10 PrzemyslawKlys

@jschpp any luck with creating this? I believe this would be greatly beneficial. Seeing as Integrated Auth will soon be a thing, I think we mostly miss Signing

PrzemyslawKlys avatar Oct 09 '22 10:10 PrzemyslawKlys