我有一个C#程序,它通过检索附件并将电子邮件分类到子文件夹来管理资源邮箱。最近出现了一个问题,即客户希望向我们发送已签名的电子邮件,因此当程序检索其附件时,将保存名为“smime.p7m”的文件而不是文件附件。查看Outlook中的电子邮件时,此文件不存在,只有我们想要的附件。但是,在单步执行代码时,Email对象中列出的附件仅包含此.p7m
文件。
我从电子邮件中检索了mime内容,但它只是字节。当我在文本编辑器中查看.p7m文件时,我会在底部文件中看到我想要的文件的内容(最终的挑逗)!如何获取原始附件而无需解析.p7m文件中的感兴趣内容?
Exchange服务器是2010 SP2,这都是通过使用EWS托管API的C#程序实现的。
答案 0 :(得分:3)
您可以使用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
的单个附件。您可以使用SignedCMS
类重复上述过程,以显示其内容。 {@ 1}}调用应该省略。
然后,您必须解析/解码MIME以提取其正文和附件。
执行此操作的代码显然位于Decrypt
命名空间,但Microsoft无论出于何种原因都不提供公共入口点。我在其他地方读过你可以用反射来访问它。这样做的缺点是,它不受支持,并且非公共接口在更高版本的框架中可能会发生变化。 this question中的代码向您展示了如何处理System.Net.Mime
传输编码。
或者,您可以像我一样编写或借用自己的MIME解析器。不幸的是,由于IP,我无法给你代码。
当时我无法找到一个简单的替代方案。现在我很想尝试下面链接的NuGet包,为自己省点痛苦。从OpenPOP.Net开始。
您可以使用code in this project获取灵感,查看this question中的第三方选项,或在NuGet上尝试these packages。
答案 1 :(得分:2)
您应该查看MimeKit(MIME解析器+ S / MIME和PGP支持)和MailKit(如果您需要SMTP,POP3和/或IMAP)。
我已经写了一些关于如何在GitHub项目主页上的文档中使用MimeKit的解密和签名验证API的例子。
答案 2 :(得分:1)
使用可通过NuGet和EWS托管API访问的OpenPOP.NET,我能够检索嵌入在某个感兴趣的电子邮件的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保存到我选择的目录中。
答案 3 :(得分:0)
最近3天,我尝试从已签名但未加密的电子邮件中提取附件。。我们的项目位于vb.net中,但应该很容易将其重写为c#。 以下是对我有用的步骤:
If String.Equals(origMessage.Attachments.First.ContentType, "multipart/signed",
StringComparison.OrdinalIgnoreCase) AndAlso
String.Equals(origMessage.Attachments.First.Name, "smime.p7m", StringComparison.OrdinalIgnoreCase) Then
Dim smimeFile As FileAttachment = origMessage.Attachments.First
smimeFile.Load()
Dim memoryStreamSigned As MemoryStream = New MemoryStream(smimeFile.Content)
Dim entity = MimeEntity.Load(memoryStreamSigned)
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
'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))
现在,您已将附件文件解码为字节数组,您可以保存它或做任何您想做的事情:)希望对您有所帮助!
答案 4 :(得分:0)
MimeKit。
我对此有误:
mltipartAttachments(i).Content.DecodeTo(fileStrm)
“内容”不是“ MimeEntity”的成员
我通过以下方法解决了此问题:
Dim mp As MimePart = mltipartAttachments(i)
mp.Content.DecodeTo(fileStrm)