1

I am using EWS to access an exchange 2013 server and gather emails from the inbox of that server. I need to be able to parse through the emails that are received at that box, which will include both encrypted and non encrypted emails. I have the .pfx file for decryption of the encrypted emails, but I am not sure of the proper way of encrypting these emails and have not found any good articles on google at this point. Can anyone assist?

Below is a sample of code that I am using (note that this is after reading lots of articles, so some stuff may not work together the way I think it should).

        var exchangeEmailHelper = new ExchangeEmailHelper();
        List<EmailMessage> = exchangeEmailHelper.getEmails();

        foreach (var email in emails)
        {
            string[] retValue = null;

            string[] mimeLines = Encoding.UTF8.GetString(email.MimeContent.Content).Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
            Console.WriteLine("mimeLines has been read");
            //find out where the encoded message starts
            int ln;
            for (ln = 0; ln < mimeLines.Length; ln++)
            {
                if (mimeLines[ln] == "MIME-Version: 1.0") break;
            }
            Console.WriteLine($"There are {ln} lines until you get to the mime version.");

            StringBuilder sb = new StringBuilder(email.MimeContent.Content.Length);
            for (int sb1 = ln + 1; sb1 < mimeLines.Length; sb1++)
            {
                sb.Append(mimeLines[sb1]);
            }

            var y = Encoding.ASCII.GetBytes(sb.ToString());


            string test1 = Regex.Replace(email.MimeContent.ToString(), @"\t|\n|\r", "");
            test1 = test1.Substring(test1.IndexOf("Content-Transfer-Encoding: base64") + 33);

            var bytearray = Encoding.ASCII.GetBytes(test1);



            var collection = new X509Certificate2Collection();
            collection.Import(ConfigurationManager.AppSettings["certLocation"], ConfigurationManager.AppSettings["certPassword"], X509KeyStorageFlags.PersistKeySet);

            var certificate = collection[0];
            var privateKey = certificate.PrivateKey as RSACryptoServiceProvider;
            var data = privateKey.Decrypt(bytearray, false);
dmoore1181
  • 1,793
  • 1
  • 25
  • 57
  • For clarification, I am able to get the EmailMessage down from the server, I just need assistance in how to decrypt the emails for parsing. Thank you. – dmoore1181 Dec 27 '18 at 15:45
  • Also, I want to avoid using any third party packages if at all possible. – dmoore1181 Dec 27 '18 at 15:50
  • Does https://stackoverflow.com/a/37894914/7419043 help? – nilekirk Dec 27 '18 at 16:09
  • @nilekirk, this very well may be part of the answer, but I am not sure exactly how to get the encrypted data out of the Email Message. I have attempted this solution, but I am now getting a CryptographicException saying The data to be decrypted exceeds the maximum for this modulus of 256 bytes. I will update the question with the code that I used to get to this error. – dmoore1181 Dec 27 '18 at 16:20

1 Answers1

1

This would probably be a lot simpler if you used MimeKit:

MimeMessage message;

using (var stream = new MemoryStream (email.MimeContent.Content, email.MimeContent.Length))
    message = MimeMessage.Load (stream);

var pkcs7 = message.BodyParts.OfType<ApplicationPkcs7Mime> ().FirstOrDefault ();
if (pkcs7 != null) {
    using (var ctx = new TemporarySecureMimeContext ()) {
        using (var stream = File.OpenRead (ConfigurationManager.AppSettings["certLocation"]))
            ctx.Import (stream, ConfigurationManager.AppSettings["certPassword"]);

        // decrypt the MIME part (result will be another MIME entity)
        var decrypted = pkcs7.Decrypt (ctx);

        // The decrypted MIME entity could be a message/rfc822 part (which
        // contains a message), a multipart (such as multipart/mixed) which
        // contains a list of subparts, each with their own content... or it
        // could be a regular MIME part which just has content. Assuming it
        // is just a regular MIME part:
        if (decrypted is MimePart) {
            var part = (MimePart) decrypted;

            using (var stream = File.Create ("decrypted-content.dat"))
                part.Content.DecodeTo (stream);
        }
    }
}
jstedfast
  • 35,744
  • 5
  • 97
  • 110
  • I gave this a try, but I am getting an exception when I get to the decrypted variable saying InvalidOperationException occured in MimeKit.dll with the additional information saying that Operation is not valid due to the current state of the object, but it doesn't say what about the object is causing the issue. Do you have any suggestions? – dmoore1181 Dec 27 '18 at 18:49
  • which line *exactly* throws? – jstedfast Dec 27 '18 at 18:57
  • If `pkcs7.Decrypt()` throws, then it probably means that the `application/pkcs7-mime` part is not encrypted, but is instead compressed or signed. What is the value of `pkcs7.SecureMimeType`? – jstedfast Dec 27 '18 at 18:59
  • pkcs7.SecureMimeType is Unknown – dmoore1181 Dec 27 '18 at 19:00
  • When I sent the test message I am working with I picked only to encrypt it, and did not check the box to sign it, though the application may have anyhow. – dmoore1181 Dec 27 '18 at 19:01
  • An `application/pkcs7-mime` part should have a `smime-type=...` parameter in the `Content-Type` header and that value should be one of the following values: `enveloped-data`, `signed-data`, or `compressed-data`. If MimeKit says the value is Unknown, then it means it wasn't any of those values. Use `using (var stream = File.Create ("output.txt")) pkcs7.WriteTo (stream);` to look at the raw MIME data and see what the headers say. – jstedfast Dec 27 '18 at 19:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/185848/discussion-between-jstedfast-and-dmoore1181). – jstedfast Dec 27 '18 at 19:08