using MimeKit; using Quartz; using Service.EmailServices; namespace Service.Jobs; /// /// 邮件同步定时任务 /// public class EmailSyncJob( IOptions emailSettings, IServiceProvider serviceProvider, IEmailHandleService emailHandleService, ILogger logger) : IJob { private readonly Dictionary _emailFetchServices = new(); private bool _isInitialized; public async Task Execute(IJobExecutionContext context) { try { logger.LogInformation("开始执行邮件同步任务"); // 如果未初始化,先初始化连接 if (!_isInitialized) { await InitializeConnectionsAsync(); } // 执行邮件同步 await FetchAndPostCmbTransactionsAsync(); logger.LogInformation("邮件同步任务执行完成"); } catch (Exception ex) { logger.LogError(ex, "邮件同步任务执行出错"); throw; // 让 Quartz 知道任务失败 } } /// /// 初始化所有邮箱连接 /// private async Task InitializeConnectionsAsync() { if (_isInitialized) { logger.LogWarning("连接已初始化,跳过重复初始化"); return; } try { if (emailSettings.Value.SmtpList.Length == 0) { logger.LogWarning("未配置邮箱账户,无法初始化连接"); return; } logger.LogInformation("开始初始化 {EmailCount} 个邮箱连接...", emailSettings.Value.SmtpList.Length); // 并行初始化所有邮箱连接 var tasks = emailSettings.Value.SmtpList.Select(async emailConfig => { try { var emailFetchService = ActivatorUtilities.CreateInstance(serviceProvider); var success = await emailFetchService.ConnectAsync( emailConfig.ImapHost, emailConfig.ImapPort, emailConfig.UseSsl, emailConfig.Email, emailConfig.Password); if (success) { _emailFetchServices[emailConfig.Email] = emailFetchService; logger.LogInformation("邮箱 {Email} 连接建立成功", emailConfig.Email); } else { logger.LogError("邮箱 {Email} 连接建立失败", emailConfig.Email); } } catch (Exception ex) { logger.LogError(ex, "初始化邮箱 {Email} 连接时出错", emailConfig.Email); } }); await Task.WhenAll(tasks); _isInitialized = true; logger.LogInformation("所有邮箱连接初始化完成,成功连接 {Count} 个邮箱", _emailFetchServices.Count); } catch (Exception ex) { logger.LogError(ex, "初始化邮箱连接失败"); } } /// /// 抓取并处理招商银行邮件交易 /// private async Task FetchAndPostCmbTransactionsAsync() { try { if (_emailFetchServices.Count == 0) { logger.LogWarning("没有可用的邮箱连接,跳过抓取"); return; } logger.LogInformation("开始抓取 {EmailCount} 个邮箱的邮件", _emailFetchServices.Count); // 并行处理多个邮箱 var tasks = _emailFetchServices.Select(async kvp => { var email = kvp.Key; var emailFetchService = kvp.Value; try { // 获取未读邮件 var unreadMessages = await emailFetchService.FetchUnreadMessagesAsync(); logger.LogInformation("邮箱 {Email} 获取到 {MessageCount} 封未读邮件", email, unreadMessages.Count); // ReSharper disable once UnusedVariable foreach (var (message, uid) in unreadMessages) { try { logger.LogDebug("邮件信息 - 发送者: {From}, 主题: {Subject}, 接收时间: {Date}", message.From, message.Subject, message.Date); logger.LogDebug("邮件内容预览: {Preview}", GetEmailBodyPreview(message)); if (await emailHandleService.HandleEmailAsync( email, message.From.ToString(), message.Subject, message.Date.DateTime, message.TextBody ?? message.HtmlBody ?? string.Empty ) || (DateTime.Now - message.Date.DateTime > TimeSpan.FromDays(3))) { #if DEBUG logger.LogDebug("DEBUG 模式下,跳过标记已读步骤"); #else // 标记邮件为已读 await emailFetchService.MarkAsReadAsync(uid); #endif } } catch (Exception ex) { logger.LogError(ex, "处理邮件时出错"); } } logger.LogInformation("邮箱 {Email} 邮件抓取完成", email); } catch (Exception ex) { logger.LogError(ex, "邮箱 {Email} 邮件抓取失败", email); } }); await Task.WhenAll(tasks); logger.LogInformation("所有邮箱邮件抓取完成"); } catch (Exception ex) { logger.LogError(ex, "抓取邮件异常"); } } /// /// 获取邮件内容预览 /// private static string GetEmailBodyPreview(MimeMessage message) { var body = message.HtmlBody ?? message.TextBody ?? string.Empty; var preview = body.Length > 100 ? body.Substring(0, 100) + "..." : body; return preview.Replace("\n", " ").Replace("\r", ""); } }