You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.09 03:03:12