构造多部分 MIME 消息而不将其保存在内存中
Posted
技术标签:
【中文标题】构造多部分 MIME 消息而不将其保存在内存中【英文标题】:Construct a multipart MIME message without holding it in memory 【发布时间】:2021-03-10 03:45:52 【问题描述】:我想从一些流中可用的部分数据(例如打开的文件句柄)中创建一个多部分 MIME 消息,并且我希望通过流发送生成的多部分 MIME 消息(例如作为一部分的网络端口HTTP 连接)。
但是,这些部分的大小为数 GB,因此我不想将它们保存在内存中,并且我不希望多部分 MIME 消息需要完全保存在内存中。
那么,如何创建多部分 MIME 消息而不将其保存在内存中,即在部分中流式传输并让它“即时”流出构造的消息?
我想使用第 3 方 MIME 库,但不知道是否支持这样的流式传输,并且我不愿意编写自己的。
有什么推荐的做法吗?
【问题讨论】:
唯一的做法是覆盖发送方法并在参数列表中包含文件名。 不确定我是否做错了什么...我真的很想知道哪个 MIME 库具有此流式传输功能,我将其发布为一个问题,但它已作为征求建议的请求而关闭,所以我根据我的基本要求重新表述了这个问题,但这已经被否决了。我认为问是否有解决我的问题的现有解决方案是一个合理的问题,但我的措辞是否有误? 这里有两个很好的链接。第一个是电子邮件 (social.msdn.microsoft.com/Forums/en-US/…) 第 3 段说你需要两个 '\r\n" 在 mime 附件之前。第二个是 Wiki (en.wikipedia.org/wiki/MIME)。当你在 Net 中使用 html 库发帖时,你附上了在调用不是你想要的方法之前的整个 mime。是创建你自己的继承 HttpWebRequest 的类,这样你就可以覆盖标准请求并添加你自己的方法来使用流发布。 @jdweng 感谢您的建议和提示!我的问题的核心实际上是“任何 mime 库都已经这样做了”,看起来答案是我需要推出自己的系统。\r\n
是一个很好的提示。我实际上并没有通过 HTTP 发送它,所以可以处理它的那一面。
唯一的库我知道你将输出的 xml 作为字符串而不是流传递。
【参考方案1】:
MimeKit 支持从磁盘而不是内存中流式传输 MimeParts 的内容,但我不确定是否有任何 HTTP 库会为您提供原始 Socket 或 NetworkStream(或 SslStream)来写入消息。
假设 HTTP 库不是限制因素,您可以像这样在 MimeKit 中创建 MimePart:
var part = new MimePart ("application", "octet-stream")
Content = new MimeContent (File.OpenRead ("large-file.dat")),
ContentTransferEncoding = ContentENcoding.Base64,
FileName = "large-file.dat"
;
你可以像这样创建一个多部分:
var multipart = new Multipart ("mixed");
multipart.Add (part);
您可以像这样将 multipart 设置为 MimeMessage 的主体(尽管我不确定您是否真的需要 MimeMessage 容器来完成您打算做的事情):
message.Body = multipart;
您可以像这样将消息(或多部分)流式传输到网络流(或任何类型的流):
message.WriteTo (stream);
如果您需要确保即使在 Unix 系统上也将消息转换为使用 CRLF,您可以这样做:
var options = FormatOptions.Default.Clone ();
options.NewLineFormat = NewLineFormat.Dos;
message.WriteTo (options, stream);
这将通过过滤器推送消息数据,该过滤器将在写入输出流时转换行尾(如果需要转换)。
由于消息数据被分成大约 4k 块,它应该符合您的要求。
如果您还有其他问题,请在 GitHub 上找到我的电子邮件地址(相同的别名,我是 MimeKit/MailKit 的作者,所以我应该很容易找到)并给我发电子邮件。我很乐意回答您有关如何执行此操作的任何问题。
事实上,MimeKit 旨在完全按照您的意愿行事并确保一切正常,我编写了 MailKit 的原始 SmtpClient。然后我在周末写了 Pop3Client 来测试我可以解析直接从套接字读取的消息。
是的,它可以做你需要它做的事情。
【讨论】:
非常感谢,正是我想要的 :-)【参考方案2】:经过进一步研究(受上面MimeKit
示例的启发),.Net HTTP 类以与MimeKit
类似的方式支持我正在寻找的内容。
创建一个MultipartContent
并使用StreamContent
添加部分,然后使用MultipartContent.ReadAsStreamAsync
获取多部分消息的流,直到多部分流需要它时才会读取部分流。这意味着(从监控进程大小)原始部分永远不会完全在内存中,多部分消息也不会。
【讨论】:
以上是关于构造多部分 MIME 消息而不将其保存在内存中的主要内容,如果未能解决你的问题,请参考以下文章