using OASystem.API.OAMethodLib.DeepSeekAPI; using OASystem.API.OAMethodLib.Hotmail; using OASystem.API.OAMethodLib.JuHeAPI; using OASystem.API.OAMethodLib.QiYeWeChatAPI; using OASystem.Domain.ViewModels.QiYeWeChat; using System.Text.Json; using System.Text.Json.Serialization; using System.Web; using static OASystem.API.OAMethodLib.Hotmail.HotmailService; namespace OASystem.API.OAMethodLib.Quartz.Business { /// /// 获取hotmail邮件,自动总结邮件内容发送至企业微信邮件 /// public static class ProcessAndNotifySummary { private static readonly SqlSugarClient _sqlSugar = AutofacIocManager.Instance.GetService(); private static readonly IQiYeWeChatApiService _qiYeWeChatApiService = AutofacIocManager.Instance.GetService(); private static readonly HotmailService _hotmailService = AutofacIocManager.Instance.GetService(); private static readonly IDeepSeekService _deepSeekService = AutofacIocManager.Instance.GetService(); private static readonly Microsoft.Extensions.Logging.ILogger _logger =AutofacIocManager.Instance.GetService().CreateLogger("ProcessAndNotifySummary"); /// /// hotmail 邮件 汇总 发送企微邮件 /// 时间范围 昨天 /// public static async void ProcessAndNotifySummaryAsync() { _logger.LogInformation("Hotmail 定时发送邮件 -> 开始"); var hotmailConfigs = await _hotmailService.GetUserMailConfigListAsync(_sqlSugar); if (hotmailConfigs == null || !hotmailConfigs.Any()) return; _logger.LogInformation("Hotmail 定时发送邮件 -> 获取基础配置"); var hotmails = hotmailConfigs.Select(x => x.UserName).ToList(); var userIds = hotmailConfigs.Select(x => x.UserId).ToList(); var cstZone = CommonFun.GetCstZone(); var nowInCst = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, cstZone); var yesterdayStart = nowInCst.Date.AddDays(-1); var yesterdayEnd = yesterdayStart.AddDays(1).AddTicks(-1); _logger.LogInformation("Hotmail 定时发送邮件 -> 获取Hotmail邮件信息 -> 开始"); // 获取邮件信息 var emailInfos = await _hotmailService.GetMergedMessagesAsync(hotmails, yesterdayStart, yesterdayEnd); _logger.LogInformation("Hotmail 定时发送邮件 -> 获取Hotmail邮件信息 -> 结束"); // 处理无邮件情况 if (emailInfos == null || !emailInfos.Any()) { _logger.LogInformation("Hotmail 定时发送邮件 -> 获取Hotmail邮件信息 -> 发送无邮件情况"); await NotifyEmptyEmails(userIds); return; } //// 预处理:限制每封邮件正文长度,防止 Token 溢出 //foreach (var mail in emailInfos) //{ // mail.Content = CleanHtmlToPlainText(mail.Content); //} _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 开始"); // 调用 AI var question = BuildMailSummaryPrompt(emailInfos); var res = await _deepSeekService.ChatAsync(question); if (res.Success) { _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 分析成功"); // 清洗 AI 可能带出的 Markdown 格式符 string cleanJson = res.Answer.Trim(); if (cleanJson.StartsWith("```json")) cleanJson = cleanJson.Replace("```json", "").Replace("```", "").Trim(); try { _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 解析AI返回的json -> 开始"); var aiSummaryResults = JsonConvert.DeserializeObject>(cleanJson); var users = await _sqlSugar.Queryable().Where(x => x.IsDel == 0 && userIds.Contains(x.Id)).Select(x => new { x.Id, x.Email }).ToListAsync(); foreach (var hotmailConfig in hotmailConfigs) { var qwEmail = users.FirstOrDefault(x => x.Id == hotmailConfig.UserId)?.Email; if (string.IsNullOrEmpty(qwEmail)) continue; if (hotmailConfig.UserName.Equals("925554512@qq.com") || hotmailConfig.UserName.Equals("Roy.Lei.Atom@hotmail.com")) { if (aiSummaryResults.Any(x => x.Recipient.Equals("925554512@qq.com"))) { hotmailConfig.UserName = "925554512@qq.com"; } if (aiSummaryResults.Any(x => x.Recipient.Equals("Roy.Lei.Atom@hotmail.com"))) { hotmailConfig.UserName = "Roy.Lei.Atom@hotmail.com"; } } // 获取 AI 为该账号生成的摘要 var summary = aiSummaryResults?.FirstOrDefault(x => x.Recipient.Equals(hotmailConfig.UserName, StringComparison.OrdinalIgnoreCase)); string finalSubject = $"{DateTime.Now:yyyy-MM-dd} - 邮件汇总"; string finalBody = $"Hotmail账号 {hotmailConfig.UserName} 在 {yesterdayStart:yyyy-MM-dd HH:mm:ss} 至 {yesterdayEnd:yyyy-MM-dd HH:mm:ss} 时间段内,未查询到收件箱邮件信息。"; if (summary != null) { finalSubject = $"[AI汇总] {summary.EmailSubject}"; finalBody = summary.TextBody; } // 测试阶段默认发送在我的邮箱 string defualtEmail1 = "johnny.yang@pan-american-intl.com"; string defualtEmail2 = "Roy.lei@pan-american-intl.com"; _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 解析AI返回的json -> 发送腾讯邮件 -> {email} 开始", qwEmail); var seedRes = await _qiYeWeChatApiService.EmailSendAsync(new EmailRequestDto { ToEmails = new List { qwEmail, defualtEmail1, defualtEmail2 }, Subject = finalSubject, Body = finalBody, }); if (seedRes.errcode == 0) { _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 解析AI返回的json -> 发送腾讯邮件 -> {email} 发送成功", qwEmail); } else { _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 解析AI返回的json -> 发送腾讯邮件 -> {email} 失败:【{ErrorMsg}】", qwEmail,seedRes.errmsg); } } } catch (Exception ex) { // 记录解析 JSON 失败日志 _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 解析AI返回的json -> 失败:{ErrorMsg}", ex.Message); } } _logger.LogInformation("Hotmail 定时发送邮件 -> DeepSeek AI 分析汇总邮件 -> 分析成功"); } /// /// 纯正则实现:剔除 HTML 标签、样式和脚本,保留核心文本 /// private static string CleanHtmlToPlainText(string? html) { if (string.IsNullOrEmpty(html)) return string.Empty; // 1. 剔除脚本 (Script) 和 样式 (Style) 及其内部内容 html = Regex.Replace(html, @"<(script|style)[^>]*?>.*?", "", RegexOptions.IgnoreCase | RegexOptions.Singleline); // 2. 剔除所有 HTML 标签 html = Regex.Replace(html, @"<[^>]*>", " "); // 3. 将 HTML 实体字符转换回普通字符 (例如   -> 空格, < -> <) html = HttpUtility.HtmlDecode(html); // 4. 清理多余的空白字符和重复换行 html = Regex.Replace(html, @"\s+", " "); // 将多个空格/换行合并为一个空格 html = Regex.Replace(html, @"(\n\s*){2,}", "\n"); // 压缩重复换行 return html.Trim(); } public static string BuildMailSummaryPrompt(List mailList) { var rawDataJson = System.Text.Json.JsonSerializer.Serialize(mailList, new JsonSerializerOptions { WriteIndented = false }); return $@" # Role: .NET 邮件情报分析引擎 (JSON-ONLY Mode) ## Task 解析以下 `rawDataJson` 数据,按 `Recipient` (收件人) 分组并生成深度分析简报。 ## Constraints (Strict) 1. **Output Format**: 只输出标准的 JSON 数组代码块。严禁包含任何开场白、结尾问候、Markdown 解释文字或非 JSON 字符。 2. **HTML Rule**: `TextBody` 字段内仅允许使用 `` 和 `
`。严禁使用 `\n`、`
` 或其他标签。 3. **Naming Convention**: - 字典 Key/属性名: 必须使用 **PascalCase** (如: Recipient, EmailSubject, TextBody)。 - 内部逻辑变量: 使用 **camelCase**。 4. **Logic**: - 按请求中的 `to` 字段进行分组。 - 分析每组邮件的业务关联性,生成 [当日概览]、[详情摘要]、[分析结论]。 ## Output Schema [ {{ ""Recipient"": ""string"", ""EmailSubject"": ""每日情报分析报告"", ""TextBody"": ""[收件人:...]

[核心概览]
...分析内容...

[分析结论]
..."" }} ] ## Input Data {rawDataJson} ## Execution Now, output the JSON array based on the logic above. No prose, no chat, just the JSON block."; } private static async Task NotifyEmptyEmails(List userIds) { var userEmails = await _sqlSugar.Queryable().Where(x => x.IsDel == 0 && userIds.Contains(x.Id)).Select(x => x.Email).ToListAsync(); if (userEmails.Any()) { await _qiYeWeChatApiService.EmailSendAsync(new EmailRequestDto { ToEmails = userEmails, Subject = $"{DateTime.Now:yyyy-MM-dd} - 邮件汇总", Body = "昨日暂未收到有效邮件。" }); } } public class AiSummaryResult { public string Recipient { get; set; } = string.Empty; public string EmailSubject { get; set; } = string.Empty; public string TextBody { get; set; } = string.Empty; } } }