Search code examples
c#emailattachmentews-managed-apismime

EWS: Retrieving attachments from signed emails


I have a C# program that manages a resource mailbox by retrieving attachments and categorizing emails into sub-folders. An issue came up recently where the client wishes to send us signed emails, so when the program retrieves their attachments a file named "smime.p7m" is saved instead of the file attachments. This file is not present when reviewing the email in Outlook, only the attachments we want. However, when stepping through the code, the attachments listed in the Email object only contains this .p7m file.

I have retrieved the mime content from the email, but it's just bytes. When I look at the .p7m file in a text editor, I see the contents of the file(s) I want at the bottom file (the ultimate tease)! How do I get the original attachments without having to parse the .p7m file for the content of interest?

The exchange server is 2010 SP2, and this is all happening via a C# program utilizing the EWS Managed API.


Solution

  • You can use the EnvelopedCMS class to get the MIME from the encrypted attachment. Assuming your security context has access to the key.

    byte[] content = ...The byte[] from the smime.p7m attachment ...
    var encrypted = new EnvelopedCms();
    encrypted.Decode(content);
    encrypted.Decrypt();
    byte[] unencryptedButRawMimeEntity = encrypted.ContentInfo.Content;
    

    This will allow you to get the unencrypted MIME Entity (the original email without transport headers).

    Note if the message is signed, the decrypted MIME entity will be another single attachment with an SMIME Type Header equal to signed-data. You can repeat the process above using the SignedCMS class, to expose its content. The Decrypt call should be omitted.

    You then have to parse/decode the MIME to extract its body and attachments.

    The code to do this obviously resides the System.Net.Mime namespace but Microsoft, for whatever reason, offer no public entry point to it. I have read elsewhere than you can use reflection to access it. This disadvantages of this is, its not supported and the non-public interface is subject to change in later versions of the framework. The code in this question shows you how to deal with a quoted-printable Transfer Encoding.

    Alternatively, you can write or borrow your own MIME parser, as I did. Unfortunately, I can't give you the code because of IP.

    At the time I was unable to find a simple alternative. Now I'd be tempted to try out the NuGet packages linked below and save myself some pain. Starting with OpenPOP.Net.


    You could use the code in this project for inspiration, look at the third-party options in this question, or try these packages on NuGet.