Initial_commit_SecMPS_v2

This commit is contained in:
2026-05-15 23:22:48 +08:00
commit 23ea4fe05f
13830 changed files with 298675 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VolPro.Core.BackgroundServices.mail;
using VolPro.Core.PerformanceMonitor;
namespace VolPro.Core.BackgroundServices
{
public static class BackgroundServiceExtensions
{
public static IServiceCollection AddBackgroundServices(this WebApplicationBuilder builder)
{
// 注册邮件服务
builder.Services.AddSingleton<IMailService, MailService>();
// 注册邮件后台服务
builder.Services.AddHostedService<MailBackgroundService>();
return builder.Services;
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VolPro.Core.BackgroundServices.mail
{
/// <summary>
/// 邮件服务接口
/// </summary>
public interface IMailService
{
/// <summary>
/// 直接发送邮件(同步发送)
/// </summary>
/// <param name="email">接收人邮箱,多个用逗号分隔</param>
/// <param name="subject">主题</param>
/// <param name="body">内容</param>
/// <param name="isHtml">是否HTML</param>
/// <returns></returns>
Task SendAsync(string email, string subject, string body, bool isHtml = true);
/// <summary>
/// 异步发送邮件(加入队列)
/// </summary>
/// <param name="email">接收人邮箱,多个用逗号分隔</param>
/// <param name="subject">主题</param>
/// <param name="body">内容</param>
/// <param name="isHtml">是否HTML</param>
/// <returns></returns>
Task SendQueuedAsync(string email, string subject, string body, bool isHtml = true);
/// <summary>
/// 发送邮件(加入队列,同步方法)
/// </summary>
/// <param name="email">接收人邮箱,多个用逗号分隔</param>
/// <param name="subject">主题</param>
/// <param name="body">内容</param>
/// <param name="isHtml">是否HTML</param>
void Send(string email, string subject, string body, bool isHtml = true);
}
}

View File

@@ -0,0 +1,85 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Quartz.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
namespace VolPro.Core.BackgroundServices.mail
{
/// <summary>
/// 邮件后台服务使用Channel队列处理邮件发送
/// </summary>
public class MailBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
public MailBackgroundService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Console.WriteLine("发送邮件服务已启动");
while (!stoppingToken.IsCancellationRequested)
{
try
{
// 从队列中读取邮件请求
var mailRequest = await MailService.MailQueue.Reader.ReadAsync(stoppingToken);
if (mailRequest.RetryCount > mailRequest.MaxRetryCount)
{
break;
}
using (var scope = _serviceProvider.CreateScope())
{
var mailService = scope.ServiceProvider.GetRequiredService<IMailService>();
try
{
await mailService.SendAsync(mailRequest.MailMessage.To,
mailRequest.MailMessage.Subject,
mailRequest.MailMessage.Body,
mailRequest.MailMessage.IsHtml);
}
catch (Exception ex)
{
mailRequest.RetryCount++;
Console.WriteLine($"邮件发送异常:{ex.Message + ex.StackTrace}");
Core.Services.Logger.AddAsync($"邮件发送异常:{ex.Message + ex.StackTrace}");
}
}
}
catch (ChannelClosedException)
{
// 队列已关闭,退出循环
break;
}
catch (OperationCanceledException)
{
// 取消令牌触发,退出循环
break;
}
catch (Exception)
{
// 邮件队列处理出现未知错误,短暂延迟后继续处理
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
}
}
public override async Task StopAsync(CancellationToken cancellationToken)
{
// 关闭队列写入器
MailService.MailQueue.Writer.Complete();
// 等待所有待处理的邮件完成
await base.StopAsync(cancellationToken);
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VolPro.Core.BackgroundServices.mail
{
/// <summary>
/// 邮件请求模型,用于队列处理
/// </summary>
public class MailRequest
{
/// <summary>
/// 请求ID
/// </summary>
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// 邮件消息
/// </summary>
public required MailRequestMessage MailMessage { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 重试次数
/// </summary>
public int RetryCount { get; set; } = 0;
/// <summary>
/// 最大重试次数
/// </summary>
public int MaxRetryCount { get; set; } = 5;
/// <summary>
/// 下次重试时间
/// </summary>
public DateTime? NextRetryTime { get; set; }
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VolPro.Core.BackgroundServices.mail
{
/// <summary>
/// 邮件消息模型
/// </summary>
public class MailRequestMessage
{
/// <summary>
/// 收件人地址
/// </summary>
public string To { get; set; }
/// <summary>
/// 抄送人地址
/// </summary>
public string Cc { get; set; }
/// <summary>
/// 密送人地址
/// </summary>
public string Bcc { get; set; }
/// <summary>
/// 邮件主题
/// </summary>
public required string Subject { get; set; }
/// <summary>
/// 邮件内容
/// </summary>
public required string Body { get; set; }
/// <summary>
/// 是否为HTML格式
/// </summary>
public bool IsHtml { get; set; } = true;
/// <summary>
/// 附件路径列表
/// </summary>
public List<string> Attachments { get; set; } = new List<string>();
/// <summary>
/// 优先级
/// </summary>
public MailPriority Priority { get; set; } = MailPriority.Normal;
}
/// <summary>
/// 邮件优先级
/// </summary>
public enum MailPriority
{
Low = 0,
Normal = 1,
High = 2
}
}

View File

@@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Threading.Channels;
using System.Threading.Tasks;
using VolPro.Core.Configuration;
using VolPro.Core.Extensions;
namespace VolPro.Core.BackgroundServices.mail
{
/// <summary>
/// 邮件服务实现
/// </summary>
public class MailService : IMailService
{
// 邮件队列Channel
private static readonly Channel<MailRequest> _mailQueue;
// 提供静态访问Channel的方法
public static Channel<MailRequest> MailQueue => _mailQueue;
// 邮件配置信息
private static string address { get; set; }
private static string authPwd { get; set; }
private static string name { get; set; }
private static string host { get; set; }
private static int port;
private static bool enableSsl { get; set; }
static MailService()
{
// 初始化邮件队列Channel
_mailQueue = Channel.CreateBounded<MailRequest>(new BoundedChannelOptions(1000)
{
FullMode = BoundedChannelFullMode.Wait
});
// 读取邮件配置
var section = AppSetting.GetSection("Mail");
address = section["Address"];
authPwd = section["AuthPwd"];
name = section["Name"];
host = section["Host"];
port = section["Port"].GetInt();
enableSsl = section["EnableSsl"].GetBool();
}
public MailService()
{
}
/// <summary>
/// 实际发送邮件的核心方法
/// </summary>
private async Task SendEmailCoreAsync(string emails, string subject, string body, bool isHtml = true)
{
// 解析多个接收人
var recipients = new List<string>();
if (!string.IsNullOrEmpty(emails))
{
foreach (var addr in emails.Split(',', StringSplitOptions.RemoveEmptyEntries))
{
recipients.Add(addr.Trim());
}
}
if (recipients.Count == 0)
{
return;
}
// 创建邮件消息
using var message = new MailMessage
{
From = new MailAddress(address, name)
};
// 添加收件人
foreach (var recipient in recipients)
{
message.To.Add(recipient);
}
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = isHtml;
// 配置SMTP客户端
using var smtpClient = new SmtpClient
{
Host = host,
Port = port,
EnableSsl = enableSsl,
Credentials = new NetworkCredential(address, authPwd),
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false
};
// 发送邮件
await smtpClient.SendMailAsync(message);
}
/// <summary>
/// 异步发送邮件(加入队列)
/// </summary>
private async Task SendEmailQueuedAsync(MailRequestMessage mailMessage)
{
var request = new MailRequest
{
MailMessage = mailMessage,
CreatedAt = DateTime.UtcNow
};
await _mailQueue.Writer.WriteAsync(request);
}
public void Send(string email, string subject, string body, bool isHtml = true)
{
if (string.IsNullOrEmpty(email))
{
return;
}
// 支持多个接收人,用逗号分隔
var mailMessage = new MailRequestMessage
{
To = email,
Subject = subject,
Body = body,
IsHtml = isHtml
};
_mailQueue.Writer.TryWrite(new MailRequest
{
MailMessage = mailMessage,
CreatedAt = DateTime.UtcNow
});
}
/// <summary>
/// 直接发送邮件(同步发送,不加入队列)
/// </summary>
public async Task SendAsync(string email, string subject, string body, bool isHtml = true)
{
await SendEmailCoreAsync(email, subject, body, isHtml);
}
/// <summary>
/// 异步发送邮件(加入队列)
/// </summary>
public async Task SendQueuedAsync(string email, string subject, string body, bool isHtml = true)
{
try
{
if (string.IsNullOrEmpty(email))
{
return;
}
var mailMessage = new MailRequestMessage
{
To = email,
Subject = subject,
Body = body,
IsHtml = isHtml
};
await SendEmailQueuedAsync(mailMessage);
}
catch (Exception)
{
throw;
}
}
}
}