EWS: Retrieving attachments from signed emails

后端 未结 5 729
执笔经年
执笔经年 2020-12-11 07:43

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

相关标签:
5条回答
  • 2020-12-11 08:09

    I spent last 3 days trying extract attachments from signed but unencrypted email. Our project is in vb.net but it should be easy to rewrite it to c#. Here are steps which worked for me:

    1. Install Mimekit Nuget Package
    2. Correctly identify the S/Mime signed email by looking at its content type and attachment name (S/Mime signed emails always have smime.p7m file attached to it)
    If String.Equals(origMessage.Attachments.First.ContentType, "multipart/signed", 
    StringComparison.OrdinalIgnoreCase) AndAlso
    String.Equals(origMessage.Attachments.First.Name, "smime.p7m", StringComparison.OrdinalIgnoreCase) Then
    
    1. Load smime file as EWS FileAttachment and create new memoryStream out of it. Then create MimeKit.MimeEntity of this stream. Now you're using MimeKit library which is great for this stuff
    Dim smimeFile As FileAttachment = origMessage.Attachments.First
    smimeFile.Load()
    Dim memoryStreamSigned As MemoryStream = New MemoryStream(smimeFile.Content)
    Dim entity = MimeEntity.Load(memoryStreamSigned)
    
    1. Iterate over your MimeEntity instance for all attachments
    If TypeOf entity Is Cryptography.MultipartSigned Then
        Dim mltipart As Multipart = entity
        Dim attachments As MimeEntity = mltipart(0)
        If TypeOf attachments Is Multipart Then
            Dim mltipartAttachments As Multipart = attachments
            For i As Integer = 0 To mltipartAttachments.Count - 1
                If mltipartAttachments(i).IsAttachment Then
                    **'BOOM, now you're looping your attachment files one by one**
                    **'Call your decode function to read your attachment as array of Bytes**
                End If
            Next
        End If
    End If
    
    1. Read your attachment as array of Bytes. Do this inside the for of previous step.
    'Read and decode content stream
    Dim fileStrm = New MemoryStream()
    mltipartAttachments(i).Content.DecodeTo(fileStrm)
    
    Dim decodedBytes(0 To fileStrm.Length - 1) As Byte
    fileStrm.Position = 0  'This is important because .DecodeTo set the position to the end!!
    fileStrm.Read(decodedBytes, 0, Convert.ToInt32(fileStrm.Length))
    

    Now you have your attachment file decoded as an array of Bytes and you can just save it or do whatever you want :) Hope this helped!

    0 讨论(0)
  • 2020-12-11 08:26

    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.

    0 讨论(0)
  • 2020-12-11 08:26

    You should check out MimeKit (MIME parser + S/MIME and PGP support) and MailKit (if you need SMTP, POP3, and/or IMAP).

    I've written some examples on how to use MimeKit's decryption and signature verification APIs in the documentation on the main page of the GitHub project.

    0 讨论(0)
  • 2020-12-11 08:32

    MimeKit.

    I get an error with this :

    mltipartAttachments(i).Content.DecodeTo(fileStrm)
    

    'Content' is not a member of 'MimeEntity'

    I solved it with this :

    Dim mp As MimePart = mltipartAttachments(i)
    mp.Content.DecodeTo(fileStrm)
    
    0 讨论(0)
  • 2020-12-11 08:33

    Using OpenPOP.NET, which is accessible through NuGet, and EWS Managed API I was able to retrieve the attachments embedded within the mime content of a certain email of interest. I used

    System.Exchange.WebServices.Data.Item email = new System.Exchange.WebServices.Data.Item(myEmail);
    OpenPop.Mime.Message message = new OpenPop.Mime.Message(email.MimeContent.Content);
    List<OpenPop.Mime.MessagePart> validMessageParts = message.FindAllAttachments().Where(x => x.FileName.Contains(".csv") == true || x.FileName.Contains(".xlsx") == true || x.FileName.Contains(".xls") == true).ToList<MessagePart>();
    
    foreach (MessagePart messagePart in validMessageParts)
    {
      if (messagePart != null)
      {
        using (FileStream fileStream = new FileStream(savingPath + messagePart.ContentDisposition.FileName, FileMode.Create, FileAccess.ReadWrite))
        {
            messagePart.Save(fileStream);
        }
      }
    }
    

    to save all csv, xlsx, and xls in a particular email into a directory of my choice.

    0 讨论(0)
提交回复
热议问题