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

如何用C#控制台应用追踪用户邮件及开发.NET邮件合规监控系统

解决方案:邮件追踪与内容监控的.NET实现

嘿,针对你提出的两个邮件相关的.NET开发需求,我整理了具体的实现思路和代码示例,希望能帮到你:


一、C#控制台应用实现已发送邮件追踪

要追踪用户已发送的邮件,推荐使用Microsoft Graph API(EWS已逐步被微软弃用,Graph是更优选择),下面是具体实现步骤:

1. 前期准备

  • 在Azure AD中注册一个控制台类型的应用,配置Mail.Read权限(需管理员同意),记录下客户端ID、租户ID、客户端密钥。
  • 安装必要的NuGet包:
    Install-Package Microsoft.Graph
    Install-Package Microsoft.Identity.Client
    

2. 核心代码示例

using Microsoft.Graph;
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SentMailTracker
{
    class Program
    {
        private static readonly string ClientId = "你的客户端ID";
        private static readonly string TenantId = "你的租户ID";
        private static readonly string ClientSecret = "你的客户端密钥";

        static async Task Main(string[] args)
        {
            // 初始化认证提供器
            var confidentialClientApplication = ConfidentialClientApplicationBuilder
                .Create(ClientId)
                .WithTenantId(TenantId)
                .WithClientSecret(ClientSecret)
                .Build();

            var authProvider = new ClientCredentialProvider(confidentialClientApplication);
            var graphClient = new GraphServiceClient(authProvider);

            try
            {
                // 获取已发送邮件(最多100封,可调整参数)
                var sentMessages = await graphClient.Me.MailFolders.SentItems.Messages
                    .Request()
                    .Select(m => new { m.Subject, m.ToRecipients, m.SentDateTime, m.Id })
                    .Top(100)
                    .GetAsync();

                Console.WriteLine("已发送邮件列表:");
                foreach (var message in sentMessages)
                {
                    Console.WriteLine($"主题:{message.Subject}");
                    Console.WriteLine($"发送时间:{message.SentDateTime?.ToString("yyyy-MM-dd HH:mm:ss")}");
                    Console.WriteLine("收件人:");
                    foreach (var recipient in message.ToRecipients)
                    {
                        Console.WriteLine($"  - {recipient.EmailAddress.Name} <{recipient.EmailAddress.Address}>");
                    }
                    Console.WriteLine("----------------------------------------");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取邮件失败:{ex.Message}");
            }
        }
    }
}

3. 注意事项

  • 如果要追踪特定用户的邮件,需确保应用有对应的用户权限,或者使用用户认证模式(而非客户端凭证)。
  • 可以扩展代码,将邮件信息存储到数据库中,实现长期追踪。

二、.NET应用监控邮件防止工作信息泄露

这个需求需要实现收件人校验、正文敏感检测、附件检查三个核心功能,分两种场景实现:

场景1:事后审计(监控已发送邮件)

基于上面的Graph API代码,扩展检查逻辑即可:

// 在获取到sentMessages后,添加检查逻辑
foreach (var message in sentMessages)
{
    // 1. 检查收件人是否为外部邮箱
    bool hasExternalRecipients = HasExternalRecipients(message.ToRecipients, "@yourcompany.com");
    // 2. 检查正文敏感内容
    bool hasSensitiveContent = await CheckSensitiveBodyContent(graphClient, message.Id);
    // 3. 检查附件
    bool hasSensitiveAttachments = await CheckSensitiveAttachments(graphClient, message.Id);

    if (hasExternalRecipients || hasSensitiveContent || hasSensitiveAttachments)
    {
        Console.WriteLine($"⚠️ 风险邮件:{message.Subject}");
        // 这里可以添加告警逻辑,比如发送通知到管理员邮箱
    }
}

// 辅助方法示例
private static bool HasExternalRecipients(IEnumerable<Recipient> recipients, string companyDomain)
{
    foreach (var recipient in recipients)
    {
        if (!recipient.EmailAddress.Address.EndsWith(companyDomain, StringComparison.OrdinalIgnoreCase))
        {
            return true;
        }
    }
    return false;
}

private static async Task<bool> CheckSensitiveBodyContent(GraphServiceClient graphClient, string messageId)
{
    var message = await graphClient.Me.Messages[messageId].Request().Select(m => m.Body).GetAsync();
    string bodyText = message.Body.Content;
    // 简化示例:检查是否包含敏感关键词
    string[] sensitiveKeywords = { "项目机密", "客户数据", "内部文档" };
    foreach (var keyword in sensitiveKeywords)
    {
        if (bodyText.Contains(keyword))
        {
            return true;
        }
    }
    return false;
}

场景2:事前拦截(发送前检查)

如果需要在用户发送邮件前就拦截,推荐开发Outlook VSTO插件,通过订阅ItemSend事件实现:

using Outlook = Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;

namespace MailMonitorAddIn
{
    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            // 订阅邮件发送事件
            Application.ItemSend += Application_ItemSend;
        }

        private void Application_ItemSend(object Item, ref bool Cancel)
        {
            if (Item is Outlook.MailItem mailItem)
            {
                bool isRisky = false;
                string warningMsg = "";

                // 检查外部收件人
                if (HasExternalRecipients(mailItem.Recipients, "@yourcompany.com"))
                {
                    warningMsg += "邮件包含外部收件人;";
                    isRisky = true;
                }

                // 检查正文敏感内容
                if (CheckSensitiveContent(mailItem.Body))
                {
                    warningMsg += "正文包含敏感信息;";
                    isRisky = true;
                }

                // 检查附件
                if (CheckSensitiveAttachments(mailItem.Attachments))
                {
                    warningMsg += "附件包含敏感内容;";
                    isRisky = true;
                }

                if (isRisky)
                {
                    MessageBox.Show($"禁止发送:{warningMsg}", "邮件监控告警", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    Cancel = true; // 取消邮件发送
                }
            }
        }

        // 辅助方法实现和之前类似,这里省略
        private bool HasExternalRecipients(Outlook.Recipients recipients, string companyDomain)
        {
            foreach (Outlook.Recipient recipient in recipients)
            {
                if (!recipient.Address.EndsWith(companyDomain, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }
            return false;
        }

        private bool CheckSensitiveContent(string body)
        {
            string[] sensitiveKeywords = { "项目机密", "客户数据" };
            foreach (var keyword in sensitiveKeywords)
            {
                if (body.Contains(keyword))
                {
                    return true;
                }
            }
            return false;
        }

        private bool CheckSensitiveAttachments(Outlook.Attachments attachments)
        {
            string[] forbiddenExtensions = { ".docx", ".xlsx", ".pdf" };
            foreach (Outlook.Attachment attachment in attachments)
            {
                string extension = System.IO.Path.GetExtension(attachment.FileName).ToLower();
                if (forbiddenExtensions.Contains(extension))
                {
                    return true;
                }
            }
            return false;
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            // 清理资源
        }

        #region VSTO generated code

        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }
}

注意事项

  • 敏感信息检测可以进一步优化,比如使用正则表达式匹配更复杂的模式,或者集成内容安全服务提升准确率。
  • VSTO插件需要部署到用户的Outlook客户端,适合企业内部场景。

内容的提问来源于stack exchange,提问作者Magdy Ismail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:03:10