GithubHelp home page GithubHelp logo

Comments (8)

jstedfast avatar jstedfast commented on July 19, 2024

Yes, I implemented it as a list because it needs to be flexible when parsing.

from mimekit.

jstedfast avatar jstedfast commented on July 19, 2024

I'm actually surprised anyone even looked at the RFC to comment on my design. In my experience looking at other MIME parsers (in .NET or otherwise), I don't think any of the authors ever bothered even looking up what RFCs were relevant, never mind actually reading them.

So when you opened this issue, I must say, I was surprised.

I don't think I've ever gotten a message from someone with multiple mailboxes in the Sender: header, so it may be safe to make it a MailboxAddress (as opposed to an InternetAddress, which can be a group).

Since the raw header value will be preserved, I might just do that...

from mimekit.

haboustak avatar haboustak commented on July 19, 2024

Well, I think your original answer is a fair response for someone implementing a framework. I do like the whole strict in what you send and liberal in what you accept. From an API standpoint it would be nice to match the expectation of normal from the RFC, as long as - like you said - it doesn't affect the ability to access the original header. Honestly I don't fully understand the differences between internetaddress, group, and mailbox yet. My code is just grabbing MailboxAddress and casting to System.Net.MailAddress so I can separate the local part and the domain part.

I ended up reading quite a few RFC because I'm trying to implement NHIN Direct and they have plenty of references. The Direct project has guidance for using S/MIME to authenticate clinical messages between doctors. They're clear that they want to validate the subjects of the signing and encryption certificates with the sender's and recipients' addresses.They tried to qualify what they want done with the following statement:

http://wiki.directproject.org/Applicability+Statement+for+Secure+Health+Transport+Working+Version

STAs MUST perform encryption/decryption and verification functions on the basis of the actual sender(s)
and receiver(s) of the message (i.e., those who are or would be listed in an SMTP RCPT FROM (sic) and
MAIL TO (sic) commands).

I think they meant MAIL FROM and RCPT TO. I don't know what they think that clears up, but MAIL FROM requires there to only be 1 sender mailbox, even if the From header in DATA has multiple senders, and in the case where From has multiple addresses, Sender is required to identify the source mailbox (presumably this is identified by the SMTP MAIL FROM command that originated the message). I think that's the intention of Sender by both Direct Project and RFC-5322 anyway.

In my case, I get to just reject mail that's not compliant with the RFC (single From or single Sender). If there's anything I find that I can contribute back through my use of the API I'll submit some pulls.

On an unrelated note - I haven't had a chance to review your parsing code, but you get a thumbs up from me for caring about performance and spending the time to write C# using pointers. And so far everything has just worked.

from mimekit.

jstedfast avatar jstedfast commented on July 19, 2024

Interesting about the NHIN Direct requirements. I wonder if they realize that the RFC*822 headers don't have to match what the client uses for the MAIL FROM and RCPT TO commands to SMTP. But I guess that doesn't matter so long as the receiving client verifies the digital signatures by matching against the Sender/From headers.

If you need to match against the To/Cc recipients when the message was encrypted, I'll have to implement an API to return a list of who the S/MIME encryption recipients were... which means I'll have to rethink my Decrypt() APIs a bit.

If you don't need this and I'm misunderstanding what is required, let me know so I don't waste time on this :-)

As far as performance... yea, MimeKit is 25x faster than OpenPOP.NET's parser (which is the fastest I could find of the open source .NET parsers), 65x faster than MIMER and 75x faster than SharpMimeTools (which is fairly representative of most of the other .NET parsers out there). They all seem to like to use TextReader and string.Split() with bits of Regex thrown in for slowness. I guess most .NET developers have never heard of tokenizers? Anyway, let's not get me started on this rant :-)

I've got some blog posts on the performance aspect of MimeKit if you are interested:

http://jeffreystedfast.blogspot.com/2013/09/optimization-tips-tricks-used-by.html (part 1)
http://jeffreystedfast.blogspot.com/2013/10/optimization-tips-tricks-used-by.html (part 2)

Sadly, I haven't yet found a way to make MimeKit as fast a my C parser (my C parser is about 1.5x faster than MimeKit). Although, considering that my C parser is noticeably faster than most other C MIME parsers out there... that puts MimeKit in some pretty respectable territory.

from mimekit.

haboustak avatar haboustak commented on July 19, 2024

You are right. I will need access to the recipients after the envelope is parsed so that I can ensure each address in the header has a certificate whose subject matches the address based on their rules.

Ideally the certificate that is returned with the recipient would have the private key loaded. At that point I can choose to decrypt the content per-recipient.

from mimekit.

jstedfast avatar jstedfast commented on July 19, 2024

I've changed things so that MimeMessage.Sender is now a MailboxAddress instead of an InternetAdressList.

Ideally the certificate that is returned with the recipient would have the private key loaded. At that point I can choose to decrypt the content per-recipient.

You don't need to do that. You only need to decrypt for one of the recipients - once it is decrypted, it's decrypted. What you probably really want is just a list of recipient certificates that the mime part was encrypted for so that you can use those certificates to try and map them back to the individual email addresses in the To/Cc headers.

from mimekit.

haboustak avatar haboustak commented on July 19, 2024

Well I need to at least ensure I have access to the private key for the recipient's certificate. If I have the public key only, then I shouldn't be able to send or receive mail for that recipient.

One option for Decrypt() is to return a DecryptedMessage object that includes all the information available from CmsEnvelopedDataParser. This let's me verify the content encryption algorithm, the recipient certificates and keys, and then lazily load the content if the recipient trust works out. If you don't need any of that detail, you can just go straight to Content and get the decrypted MimeEntity.

public class DecryptedMessage
{
    public EncryptionAlgorithm? Algorithm { get; set; }

    public IList<SecureMimeRecipient> Recipients { get; set; }

    private MimeEntity _content = null;
    public MimeEntity Content
    {
        get { return _content ?? (_content = LoadContent()); }
        protected set { _content = value; }
    }
    ...
 }

public class SecureMimeRecipient
{
    public RecipientInformation Recipient { get; set; }
    public X509Certificate Certificate { get; set; }
    public AsymmetricKeyParameter PrivateKey { get; set; }
}

from mimekit.

haboustak avatar haboustak commented on July 19, 2024

MimeMessage.Sender in the latest version works well for all the messages I have tested it with

from mimekit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.