1

是否可以使用 MimeKit.MimeParser 从 mbox 文件中读取第 M 条消息的第 N 个附件?就我而言,我会将少量消息(每个消息的几个字段,包括附件列表)存储到内存数据结构中,之后,我希望能够返回到特定的消息附件并阅读其内容。

到目前为止我尝试过的事情:

  • 记住每条读取消息的底层流位置并将流定位到该位置,然后再调用 _parser.ParseMessage() 以获取消息及其附件。
  • 我还尝试使用 LINQ 方法通过 MessageID 获取消息,并结合将流位置设置为 0 并再次调用 SetStream 而没有它。

以上不起作用。

这里有一些代码只是为了说明我的努力:

public void SaveAttachment(Attachment att, Stream outStream)
{
     _inputStream.Seek(0, SeekOrigin.Begin);
     _parser.SetStream(_inputStream, false);
     //MimeMessage mimeMsg = _parser.Skip((int)(att.Parent as Message).Position).First();
     MimeMessage mimeMsg =_parser.SingleOrDefault(x => x.MessageId == (att.Parent as Message).EntryID);
     MimeEntity mimeAtt = mimeMsg.Attachments.ToList()[att.AttachmentIndex];
     if (mimeAtt is MessagePart)
     {
          (mimeAtt as MessagePart).Message.WriteTo(outStream);
     }
     else
     {
          (mimeAtt as MimePart).Content.DecodeTo(outStream);
     }
}
4

1 回答 1

0

是否可以使用 MimeKit.MimeParser 从 mbox 文件中读取第 M 条消息的第 N 个附件?

如果你想这样做,那么你将需要你想要的 MimeEntity 的确切流开始/结束偏移量。

然后,您要做的是使用这些流偏移将流包装在 MimeKit.IO.BoundStream 中,以防止解析器偏离这些边界并在 MimeParser 上设置 BoundStream。

设置流时,请确保使用MimeFormat.Entity(而不是 MimeFormat.Mbox),因为您只对解析单个MimeEntity(可以是包含其他 MimeEntities 的多部分)感兴趣。

要获得这些偏移量,您需要在首次解析 mbox 时订阅 MimeParser 的 MimeEntityBegin/End 事件:http: //www.mimekit.net/docs/html/Events_T_MimeKit_MimeParser.htm

我希望能够返回到特定的邮件附件并阅读其内容。

您是否查看过persistentMimeParser.SetStream() 的参数?

这可能仍然使用比您想要使用的更多的内存(因为它将加载所有标题 + 每个 MimeEntity 内容的跟踪流偏移),但您可能会发现它更方便并且内存使用量足够低以适合您的实际使用需要。

当此属性设置为 时true,它不会将每个 MimePart 的内容加载到 RAM 中,而是创建一个 BoundStream 来包装提供给 MimeParser 的流,以便当您请求这些 MimePart 的内容时,它会延迟从磁盘加载它。

默认情况下(或何时persistent = false),MimeParser 会将该内容加载到 MemoryBlockStream(实际上是一个 MemoryStream,它试图减少字节数组大小以提高性能),您可能知道,如果消息有大附件,它可能会使用相当多的内存(或很多)。

使用时要注意的persistent = true是,如果您希望能够获取解析器解析的任何 MimeParts 的内容,则需要保持 mbox 文件流打开。关闭流后,尝试获取任何 MimeParts 的内容可能会导致 ObjectDisposedException。

于 2021-07-28T15:16:26.240 回答