парсинг подписанной и зашифрованной почты - PullRequest
0 голосов
/ 04 января 2019

Я пишу приложение, которое должно уметь читать подписанные и зашифрованные электронные письма и анализировать их содержимое.Я могу заставить все работать нормально для писем, которые только зашифрованы, но не знаю, что делать, когда я получаю письмо, которое также подписано.После того, как я расшифровал это письмо, вместо ожидаемых 4-х частей в объекте Multipart, у меня есть только 1-я часть в объекте MimePart с именем файла smime.p7m.Я не знаю, как разбить этот файл или проверить подпись.Я нашел документацию по проверке подписи (http://www.mimekit.net/docs/html/Working-With-SMime.htm#Verify),, но я не вижу, как это что-то делает. Очевидно, есть кое-что, чего я просто не понимаю в данный момент.

Ниже приведенПример кода, который я использую. Обратите внимание, что он будет реорганизован после того, как я все выясню, но пока этот код работает нормально для всех писем, которые я до сих пор тестировал, которые не подписаны (могут или не могут быть зашифрованы).

public void decryptAndSendEmails()
{
    List<EmailMessage> emails = getEmails();
    foreach (var email in emails)
    {
        var decryptedEmailMessage = new EmailMessage(service);
        MimeMessage message;

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

        var pkcs7 = message.BodyParts.OfType<ApplicationPkcs7Mime>().FirstOrDefault();

        if (pkcs7 != null)
        {
            //If the SecureMimeType has not been set as it should, set it to EnvelopedData
            if (pkcs7.SecureMimeType == SecureMimeType.Unknown)
            {
                var content = new MemoryStream();
                pkcs7.Content.DecodeTo(content);
                content.Position = 0;

                pkcs7 = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, content);
            }

            using (var ctx = new TemporarySecureMimeContext())
            {
                using (var stream = File.OpenRead(ConfigurationManager.AppSettings["certLocation"]))
                {
                    ctx.Import(stream, ConfigurationManager.AppSettings["certPassword"]);
                }

                var decrypted = pkcs7.Decrypt(ctx);
                var decryptedParts = new List<MimePart>();
                if (decrypted is Multipart)
                {
                    decryptedParts = breakMultiPart((Multipart)decrypted);
                }
                else if (decrypted is MimePart)
                {
                    decryptedParts.Add((MimePart)decrypted);
                }
                else
                {
                    throw new InvalidOperationException("Unknown Mime part found");
                }

                var textParts = decryptedParts.Where(r => r is TextPart);
                var htmlParts = textParts.Where(x => ((TextPart)x).IsHtml);
                var textBodyParts = textParts.Where(x => !((TextPart)x).IsHtml);
                var attachmentParts = decryptedParts.Where(r => !(r is TextPart));

                if (htmlParts.Any())
                {
                    if (htmlParts.Count() > 1)
                    {
                        throw new InvalidOperationException("multiple html body parts.");
                    }
                    var htmlPart = (TextPart)htmlParts.First();
                    decryptedEmailMessage.Body = new MessageBody(BodyType.HTML, htmlPart.Text);
                }
                else
                {
                    //Text body
                    if (textBodyParts.Count() > 1)
                    {
                        throw new InvalidOperationException("multiple text body parts.");
                    }
                    var textPart = (TextPart)textBodyParts.First();
                    decryptedEmailMessage.Body = new MessageBody(BodyType.Text, textPart.Text);
                }

                foreach (var part in attachmentParts)
                {
                    var content = new MemoryStream();
                    part.Content.DecodeTo(content);
                    content.Position = 0;

                        decryptedEmailMessage.Attachments.AddFileAttachment(part.FileName, content);

                    if (!part.IsAttachment)
                    {
                        decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).IsInline = true;
                        decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).ContentId = part.ContentId;
                    }
                }
            }
            ////do stuff with decrypted Email
        }

        else
        {
            //The email is not encrypted
            decryptedEmailMessage = email;
            //do stuff with decrypted Email
        }
    }
}

1 Ответ

0 голосов
/ 04 января 2019

Я наконец понял это, используя комбинацию комментария от @jstedfast и информации, которую нашел в Невозможно расшифровать p7m с помощью MimeKit .Ниже приведен код для устранения этой проблемы:

public void decryptAndSendEmails()
{
List<EmailMessage> emails = getEmails();

foreach (var email in emails)
{
    var decryptedEmailMessage = new EmailMessage(service);
    MimeMessage message;

    using (var stream = new MemoryStream(email.MimeContent.Content, false))
    {
        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"]);
            }


            var decrypted = pkcs7.Decrypt(ctx);

            if (decrypted != null && decrypted is MimePart && ((MimePart)decrypted).FileName == "smime.p7m")
            {
                //We need to verify the signature
                var signedDecryptedEntity = decrypted as ApplicationPkcs7Mime;
                signedDecryptedEntity.Verify(ctx, out decrypted); //the real decrypted data
            }

            var decryptedParts = new List<MimePart>();
            if (decrypted is Multipart)
            {
                decryptedParts = breakMultiPart((Multipart)decrypted);
            }
            else if (decrypted is MimePart)
            {
                decryptedParts.Add((MimePart)decrypted);
            }
            else
            {
                throw new InvalidOperationException("Unknown Mime part found");
            }

            var textParts = decryptedParts.Where(r => r is TextPart);
            var htmlParts = textParts.Where(x => ((TextPart)x).IsHtml);
            var textBodyParts = textParts.Where(x => !((TextPart)x).IsHtml);
            var attachmentParts = decryptedParts.Where(r => !(r is TextPart));

            if (htmlParts.Any())
            {
                if (htmlParts.Count() > 1)
                {
                    throw new InvalidOperationException("multiple html body parts.");
                }
                var htmlPart = (TextPart)htmlParts.First();
                decryptedEmailMessage.Body = new MessageBody(BodyType.HTML, htmlPart.Text);
            }
            else
            {
                //Text body
                if (textBodyParts.Count() > 1)
                {
                    throw new InvalidOperationException("multiple text body parts.");
                }
                var textPart = (TextPart)textBodyParts.First();
                decryptedEmailMessage.Body = new MessageBody(BodyType.Text, textPart.Text);
            }

            foreach (var part in attachmentParts)
            {
                var content = new MemoryStream();
                part.Content.DecodeTo(content);
                content.Position = 0;

                decryptedEmailMessage.Attachments.AddFileAttachment(part.FileName, content);

                if (!part.IsAttachment)
                {
                    decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).IsInline = true;
                    decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).ContentId = part.ContentId;
                }
            }
        }
        //Do Something with email (decryptedEmailMessage)
    }

    else
    {
        //The email is not encrypted
        decryptedEmailMessage = email;
        //Do Something with email (decryptedEmailMessage)
    }

}

}

...