在.NET 4.7.2 WinForms应用中捕获从Outlook PWA拖拽的邮件为EML文件的问题
在.NET 4.7.2 WinForms应用中捕获从Outlook PWA拖拽的邮件为EML文件的问题
我最近碰到个头疼的问题:想把Outlook PWA里的邮件拖拽到.NET 4.7.2的WinForms应用中,然后将邮件保存为EML文件做后续处理。之前我们一直用经典版Outlook拖拽邮件到这个WinForms应用,用了好几年都没出过问题,换成PWA版本后就卡壳了。
我考虑过的替代方案
- Graph API:我能从Chrome的JSON数据里拿到邮件ID,理论上可以通过Graph API下载邮件,但我不想给应用授权读取用户整个邮箱的权限——毕竟只需要用户拖拽的那几封邮件而已,权限给得太大完全没必要。
- Outlook插件:这个方案比Graph API还复杂,而且同样需要访问邮箱的权限,完全不是我想要的轻量解决方案。
预期与实际情况
我本来以为WinForms应用能像拖拽到桌面一样,直接捕获邮件并保存成EML文件——毕竟我知道PWA和经典版Outlook的处理方式肯定不一样,但拖拽到桌面能正常生成EML,那应用里应该也能做到吧?结果实际拖拽时,应用能识别到的格式有这些:
- DragContext
- DragImageBits
- chromium/x-renderer-taint
- FileDrop(0字节)
- FileNameW(0字节)
- FileName(0字节)
- Chromium Web Custom MIME Data Format
我能捕获到Chromium Web Custom MIME Data Format里的数据,里面包含邮件主题、ID之类的信息,但没有能转成EML的完整邮件内容,也拿不到EML文件的链接。
观察到的现象
- 把Outlook PWA的邮件拖拽到桌面时,系统会在
%TEMP%目录生成一个名为chrome_dragxxxxx_xxxxxxxx的文件夹,里面就有EML文件。看起来不是Windows调用Graph API下载的,应该是Outlook PWA自己先下载好邮件再传过来的。 - 但拖拽到我的测试应用时,虽然也会生成这个chrome_drag文件夹,里面却是空的,啥都没有。
环境信息
- Outlook Web App(PWA模式)
- Windows 11
我到底哪里操作错了?难道我没法复刻拖拽到桌面的那种行为吗?
下面是我写的测试应用代码,就是个简单的WinForms程序,用来显示拖拽时的诊断数据:
namespace EmailDragDropDemo { public class MainForm : Form { private Label dropLabel; private TextBox formatsTextBox; public MainForm() { this.Text = "Drag-and-Drop EML Demo"; this.Width = 400; this.Height = 300; dropLabel = new Label { Text = "Drag an email here", AutoSize = false, Dock = DockStyle.Top, Height = 60, TextAlign = System.Drawing.ContentAlignment.MiddleCenter, AllowDrop = true }; formatsTextBox = new TextBox { Multiline = true, ReadOnly = true, Dock = DockStyle.Fill, ScrollBars = ScrollBars.Vertical, Font = new System.Drawing.Font("Consolas", 10), WordWrap = false }; dropLabel.DragEnter += DropLabel_DragEnter; dropLabel.DragDrop += DropLabel_DragDrop; this.Controls.Add(formatsTextBox); this.Controls.Add(dropLabel); } private void DropLabel_DragEnter(object? sender, DragEventArgs e) { // Diagnostic: Show all available data formats string[] formats = e.Data?.GetFormats() ?? new string[0]; string formatList = string.Join("\r\n", formats); formatsTextBox.Text = formatList; dropLabel.Text = "Available formats (see below):"; if (e.Data != null && e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; } private void DropLabel_DragDrop(object? sender, DragEventArgs e) { // Diagnostic: Show all available data formats and their contents string[] formats = e.Data?.GetFormats() ?? new string[0]; string formatList = string.Join("\r\n", formats); formatsTextBox.Text = formatList; string details = ""; foreach (var format in formats) { try { var data = e.Data?.GetData(format); if (data is string s) { details += $"Format: {format}\r\nContent (first 500 chars):\r\n{s.Substring(0, Math.Min(500, s.Length))}\r\n\r\n"; } else if (data is string[] arr) { details += $"Format: {format}\r\nArray Content:\r\n{string.Join("\r\n", arr)}\r\n\r\n"; } else if (data is System.IO.MemoryStream ms) { ms.Position = 0; byte[] buffer = new byte[Math.Min(256, ms.Length)]; int read = ms.Read(buffer, 0, buffer.Length); string hex = BitConverter.ToString(buffer, 0, read).Replace("-", " "); details += $"Format: {format}\r\nMemoryStream (first {read} bytes as hex):\r\n{hex}\r\n"; // Try to decode as UTF-8 text if this is the Chromium Web Custom MIME Data Format if (format.Contains("Chromium Web Custom MIME Data Format")) { ms.Position = 0; using (var reader = new StreamReader(ms, System.Text.Encoding.Unicode, true, 1024, true)) // UTF-16LE { string text = reader.ReadToEnd(); details += $"Decoded content:\r\n{text.Substring(0, Math.Min(500, text.Length))}\r\n\r\n"; } } } } catch (Exception ex) { details += $"Format: {format}\r\nError reading data: {ex.Message}\r\n\r\n"; } } formatsTextBox.Text = details; } } }
内容来源于stack exchange
相关产品推荐
相关产品推荐

