EWS: получение вложений из подписанных писем

У меня есть программа на C #, которая управляет почтовым ящиком ресурсов, извлекая вложения и распределяя электронные письма по подпапкам. Недавно возникла проблема, когда клиент желает отправлять нам подписанные электронные письма, поэтому, когда программа извлекает их вложения, вместо вложенных файлов сохраняется файл с именем «smime.p7m». Этот файл отсутствует при просмотре электронной почты в Outlook, только вложения, которые нам нужны. Однако при пошаговом выполнении кода вложения, перечисленные в объекте Email, содержат только этот .p7m файл.

Я получил содержимое mime из сообщения электронной почты, но это всего лишь байты. Когда я смотрю на файл .p7m в текстовом редакторе, я вижу содержимое файла (ов), который мне нужен, в самом нижнем файле (окончательная дразня)! Как мне получить исходные вложения, не разбирая файл .p7m на предмет интересующего содержания?

Сервер обмена - это 2010 SP2, и все это происходит с помощью программы C #, использующей управляемый API EWS.


person Grant Bartel    schedule 07.02.2014    source источник
comment
Привет, есть ли возможность сделать то же самое с помощью EWS Managed Java API. У меня есть программа Java, которая подключается к почтовому ящику и извлекает вложения. Но для подписанных писем загружается только файл Smime.p7m, а не исходный файл .txt. Любые предложения были бы действительно полезны.   -  person J M    schedule 28.05.2020


Ответы (5)


Вы можете использовать EnvelopedCMS, чтобы получить MIME из зашифрованного вложения. Предполагая, что у вашего контекста безопасности есть доступ к ключу.

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

Это позволит вам получить незашифрованный объект MIME (исходное электронное письмо без транспортных заголовков).

Примечание: если сообщение подписано, расшифрованный объект MIME будет еще одним вложением с заголовком SMIME Type, равным signed-data. Вы можете повторить описанный выше процесс, используя _ 5_, чтобы раскрыть его содержимое. Вызов Decrypt следует опустить.

Затем вам нужно проанализировать / декодировать MIME, чтобы извлечь его тело и вложения.

Код для этого, очевидно, находится в пространстве имен System.Net.Mime, но Microsoft по какой-либо причине не предлагает для него общедоступной точки входа. Я читал в другом месте, вы не можете использовать отражение для доступа к нему. Этот недостаток заключается в том, что он не поддерживается, а закрытый интерфейс может быть изменен в более поздних версиях платформы. Код в этом вопросе показывает, как поступать с quoted-printable Transfer Кодировка.

Как вариант, вы можете написать или позаимствовать свой собственный парсер MIME, как это сделал я. К сожалению, я не могу дать вам код из-за IP.

В то время я не мог найти простой альтернативы. Теперь у меня возникнет соблазн попробовать пакеты NuGet, указанные ниже, и избавить себя от боли. Начиная с OpenPOP.Net.


Вы можете использовать код в этом проекте для вдохновения, посмотрите на сторонние параметры в этом вопросе или попробуйте эти пакеты в NuGet.

person Jodrell    schedule 07.02.2014
comment
Спасибо, Джодрелл. Я посмотрю на OpenPOP.Net и посмотрю, к чему это меня приведет. Затем я опубликую все положительные результаты, которые найду :) - person Grant Bartel; 07.02.2014
comment
@Jodrell Я понимаю, что этот пост очень старый, но я надеялся, что кто-то все еще знает. Как я могу узнать, есть ли у данного контекста безопасности доступ к ключу? - person SlipEternal; 10.01.2020

Вам следует ознакомиться с MimeKit (парсер MIME + поддержка S / MIME и PGP) и MailKit (если вам нужен SMTP, POP3 и / или IMAP).

Я написал несколько примеров использования API-интерфейсов MimeKit для расшифровки и проверки подписи в документации на главной странице проекта GitHub.

person jstedfast    schedule 08.02.2014

Используя OpenPOP.NET, доступный через NuGet, и управляемый API EWS, я смог получить вложения, встроенные в mime-контент определенного интересующего письма. я использовал

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);
    }
  }
}

чтобы сохранить все csv, xlsx и xls в конкретном письме в каталог по моему выбору.

person Grant Bartel    schedule 14.02.2014
comment
Автор не спрашивает о простом обращении с вложениями. Пользователь спрашивает, как обрабатывать подписанное / зашифрованное электронное письмо, которое отображается как вложение в объектной модели. - person Marco Scheel; 04.05.2015

Последние 3 дня я провел, пытаясь извлечь вложения из подписанного, но незашифрованного сообщения электронной почты. Наш проект находится на vb.net, но его будет легко переписать на C #. Вот шаги, которые у меня сработали:

  1. Установите пакет Mimekit Nuget
  2. Правильно идентифицируйте электронное письмо, подписанное S / Mime, по его типу содержимого и имени вложения (к электронным письмам, подписанным S / Mime, всегда прикреплен файл smime.p7m)
If String.Equals(origMessage.Attachments.First.ContentType, "multipart/signed", 
StringComparison.OrdinalIgnoreCase) AndAlso
String.Equals(origMessage.Attachments.First.Name, "smime.p7m", StringComparison.OrdinalIgnoreCase) Then
  1. Загрузите файл smime как EWS FileAttachment и создайте из него новый memoryStream. Затем создайте MimeKit.MimeEntity этого потока. Теперь вы используете библиотеку MimeKit, которая отлично подходит для этого.
Dim smimeFile As FileAttachment = origMessage.Attachments.First
smimeFile.Load()
Dim memoryStreamSigned As MemoryStream = New MemoryStream(smimeFile.Content)
Dim entity = MimeEntity.Load(memoryStreamSigned)
  1. Обходите ваш экземпляр MimeEntity для всех вложений
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 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))

Теперь у вас есть прикрепленный файл, декодированный как массив байтов, и вы можете просто сохранить его или сделать что хотите :) Надеюсь, это помогло!

person DurkoMatko    schedule 14.05.2019

MimeKit.

Я получаю сообщение об ошибке:

mltipartAttachments(i).Content.DecodeTo(fileStrm)

Content не является членом MimeEntity

Я решил это с помощью этого:

Dim mp As MimePart = mltipartAttachments(i)
mp.Content.DecodeTo(fileStrm)
person Knarf    schedule 11.07.2019