邮件日志
continuous-integration/drone/push Build is passing

This commit is contained in:
he
2025-11-05 16:58:02 +08:00
parent 955ca4a1a6
commit 4d2f04b30e
11 changed files with 21549 additions and 187 deletions
@@ -16,7 +16,40 @@ public class EmailLogView : EmailLogAddOrEdit
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
public List<EmailRecipientLogView> RecipientList { get; set; }
}
public class EmailRecipientLogView
{
public Guid Id { get; set; }
/// <summary>
/// 邮件Id
/// </summary>
public Guid EmailLogId { get; set; }
/// <summary>
/// 收件人姓名
/// </summary>
public string RecipientName { get; set; }
/// <summary>
/// 收件人地址
/// </summary>
public string RecipientAddress { get; set; }
/// <summary>
/// 收件人类型
/// </summary>
public RecipientType RecipientTypeEnum { get; set; }
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
}
@@ -39,16 +72,6 @@ public class EmailLogAddOrEdit
/// </summary>
public string EmailSubject { get; set; } = string.Empty;
/// <summary>
/// 收件人
/// </summary>
public List<EmaliSendInfo> ToRecipients { get; set; }
/// <summary>
/// 抄送人
/// </summary>
public List<EmaliSendInfo> CcRecipients { get; set; }
/// <summary>
/// 附件
/// </summary>
@@ -85,19 +108,37 @@ public class EmailLogAddOrEdit
public EmailState EmailStateEnum { get; set; }
}
public class GetEmailInfoOutDto:EmailLogView
{
}
public class GetEmailInfoInDto
{
public Guid Id { get; set; }
}
public class ResendEmailInDto
{
public Guid Id { get; set; }
}
public class EmailLogQuery:PageInput
{
public Guid? TrialId { get; set; }
public DateTime? EmailStartDate { get; set; }
public DateTime? EmailEndDate { get; set; }
public EmailState EmailStateEnum { get; set; }
public string? ToRecipientName { get; set; }
public EmailState? EmailStateEnum { get; set; }
public string ToRecipientName { get; set; } = string.Empty;
public string CcRecipientName { get; set; } = string.Empty;
public string? CcRecipientName { get; set; }
}
@@ -4,6 +4,7 @@
// 生成时间 2025-10-28 06:22:42Z
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
@@ -31,92 +32,247 @@ namespace IRaCIS.Core.Application.Service;
/// <param name="_localizer"></param>
[ApiExplorerSettings(GroupName = "Common")]
public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
IRepository<EmailRecipientLog> _emailRecipientLogRepository,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService, IEmailLogService
{
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
/// <summary>
/// 获取邮件日志列表
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<EmailLogView>> GetEmailLogList(EmailLogQuery inQuery)
public async Task<PageOutput<EmailLogView>> GetEmailLogList(EmailLogQuery inDto)
{
PageOutput<EmailLogView> pageOutput = new PageOutput<EmailLogView>();
var emailLogQueryable = _emailLogRepository
.WhereIf(inDto.EmailStartDate.HasValue, x => x.EmailDate >= inDto.EmailStartDate.Value)
.WhereIf(inDto.EmailEndDate.HasValue, x => x.EmailDate <= inDto.EmailEndDate.Value)
.WhereIf(inDto.EmailStateEnum.HasValue, x => x.EmailStateEnum == inDto.EmailStateEnum.Value)
.WhereIf(inDto.CcRecipientName.IsNotNullOrEmpty(),x=>x.EmailRecipientLogList.Any(x=>x.RecipientTypeEnum==RecipientType.Cc&&x.RecipientName.Contains(inDto.CcRecipientName)))
.WhereIf(inDto.ToRecipientName.IsNotNullOrEmpty(), x => x.EmailRecipientLogList.Any(x => x.RecipientTypeEnum == RecipientType.To && x.RecipientName.Contains(inDto.ToRecipientName)))
.ProjectTo<EmailLogView>(_mapper.ConfigurationProvider);
switch (inQuery.EmailStateEnum)
var defalutSortArray = new string[] { nameof(EmailLogView.EmailDate) + " desc" };
var pageList = await emailLogQueryable.ToPagedListAsync(inDto, defalutSortArray);
return pageList;
}
/// <summary>
/// 获取单挑邮件日志详情
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<GetEmailInfoOutDto> GetEmailInfo(GetEmailInfoInDto inDto)
{
var emailInfo=await _emailLogRepository
.Where(x => x.Id == inDto.Id)
.ProjectTo<GetEmailInfoOutDto>(_mapper.ConfigurationProvider)
.FirstNotNullAsync();
if (emailInfo.UniqueId.IsNotNullOrEmpty())
{
case EmailState.Success:
using (var client = new ImapClient())
using (var client = new ImapClient())
{
try
{
client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
var sentFolder = client.GetFolder("已发送");
sentFolder.Open(FolderAccess.ReadOnly);
var uid = new UniqueId(uint.Parse(emailInfo.UniqueId));
var message = sentFolder.GetMessage(uid);
emailInfo.Content = message.HtmlBody ?? string.Empty;
sentFolder.Close();
}
catch (Exception ex)
{
}
finally
{
client.Disconnect(true);
}
}
}
return emailInfo;
}
/// <summary>
/// 重发邮件
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> ResendEmail(ResendEmailInDto inDto)
{
var emailInfo = await _emailLogRepository
.Where(x => x.Id == inDto.Id)
.ProjectTo<GetEmailInfoOutDto>(_mapper.ConfigurationProvider)
.FirstNotNullAsync();
if (emailInfo.UniqueId.IsNotNullOrEmpty())
{
using (var client = new ImapClient())
{
try
{
client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
var sentFolder = client.GetFolder("已发送");
sentFolder.Open(FolderAccess.ReadOnly);
var uid = new UniqueId(uint.Parse(emailInfo.UniqueId));
var message = sentFolder.GetMessage(uid);
emailInfo.Content = message.HtmlBody ?? string.Empty;
sentFolder.Close();
}
catch (Exception ex)
{
}
finally
{
client.Disconnect(true);
}
}
}
var messageToSend = new MimeMessage();
// 发件地址
messageToSend.From.Add(new MailboxAddress(emailInfo.SenderName, emailInfo.SenderAddress));
foreach (var item in emailInfo.RecipientList.Where(x => x.RecipientTypeEnum == RecipientType.To))
{
messageToSend.To.Add(new MailboxAddress(item.RecipientName, item.RecipientAddress));
}
foreach (var item in emailInfo.RecipientList.Where(x => x.RecipientTypeEnum == RecipientType.Cc))
{
messageToSend.Cc.Add(new MailboxAddress(item.RecipientName, item.RecipientAddress));
}
messageToSend.Subject = emailInfo.EmailSubject;
var builder = new BodyBuilder();
builder.HtmlBody = emailInfo.Content;
messageToSend.Body = builder.ToMessageBody();
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
return ResponseOutput.Ok();
}
/// <summary>
/// 同步邮件
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SynchronizationEmail()
{
var maxTime=await _emailLogRepository.MaxAsync(t => t.EmailDate);
List<EmailLog> emailList = new List<EmailLog>();
List<EmailRecipientLog> EmailRecipientLogList = new List<EmailRecipientLog>();
using (var client = new ImapClient())
{
try
{
client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
var sentFolder = client.GetFolder("已发送");
sentFolder.Open(FolderAccess.ReadOnly);
var startDate = maxTime ?? DateTime.MinValue;
var searchQuery = SearchQuery.All.And(SearchQuery.DeliveredAfter(startDate));
var uids = sentFolder.Search(searchQuery).ToList();
foreach (var uid in uids)
{
try
{
client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
var sentFolder = client.GetFolder("已发送");
sentFolder.Open(FolderAccess.ReadOnly);
//var message = sentFolder.GetMessage(uid);
// var emailView = ConvertToEmailLogView(uid, message);
// 构建搜索查询条件
var searchQuery = BuildSearchQuery(inQuery);
var orderBy = new[] { OrderBy.ReverseDate };
// 搜索符合条件的邮件UID
if (client.Capabilities.HasFlag(ImapCapabilities.Sort))
var message = sentFolder.GetMessage(uid);
var emaillog = new EmailLog
{
Console.WriteLine("服务器支持 SORT 扩展");
}
else
UniqueId = uid.ToString(),
MessageId = message.MessageId ?? string.Empty,
EmailSubject = message.Subject ?? string.Empty,
EmailDate = message.Date.UtcDateTime,
EmailStateEnum = EmailState.Success,
};
var fromMailbox = message.From.Mailboxes.FirstOrDefault();
if (fromMailbox != null)
{
Console.WriteLine("服务器不支持 SORT,需本地排序");
emaillog.SenderAddress = fromMailbox.Address;
emaillog.SenderName = fromMailbox.Name ?? string.Empty;
}
List<EmailRecipientLog> recipientLogs= new List<EmailRecipientLog>();
//var uids = sentFolder.Sort(searchQuery, orderBy).Skip((inQuery.PageIndex - 1) * inQuery.PageSize).Take(inQuery.PageSize).ToList();
int sort = 0;
message.To.Mailboxes.ForEach(x =>
{
recipientLogs.Add(new EmailRecipientLog()
{
RecipientName = x.Name ?? string.Empty,
RecipientAddress = x.Address,
EmailLogId= emaillog.Id,
RecipientTypeEnum = RecipientType.To,
Sort= sort++,
});
});
sort = 0;
message.Cc.Mailboxes.ForEach(x =>
{
recipientLogs.Add(new EmailRecipientLog()
{
RecipientName = x.Name ?? string.Empty,
RecipientAddress = x.Address,
EmailLogId = emaillog.Id,
RecipientTypeEnum = RecipientType.Cc,
Sort = sort++,
});
});
emailList.Add(emaillog);
EmailRecipientLogList.AddRange(recipientLogs);
pageOutput.TotalCount = sentFolder.Search(searchQuery).Count();
// 在内存中分页倒序
var uids = sentFolder.Search(searchQuery).Skip(CalcReverseSkip(inQuery.PageIndex, inQuery.PageSize, (int)pageOutput.TotalCount)).Take(inQuery.PageSize).ToList();
uids.Reverse();
// 获取邮件并排序(按时间倒序)
var emailList = GetEmailsWithSorting(sentFolder, uids);
pageOutput.PageIndex = inQuery.PageIndex;
pageOutput.PageSize = inQuery.PageSize;
pageOutput.CurrentPageData = emailList;
sentFolder.Close();
}
catch (Exception ex)
{
}
finally
{
client.Disconnect(true);
Console.WriteLine($"处理邮件 {uid} 失败: {ex.Message}");
}
}
return pageOutput;
case EmailState.Error:
var emailLogQueryable = _emailLogRepository
.ProjectTo<EmailLogView>(_mapper.ConfigurationProvider);
var pageList = await emailLogQueryable.ToPagedListAsync(inQuery);
return pageList;
sentFolder.Close();
}
catch (Exception ex)
{
}
finally
{
client.Disconnect(true);
}
await _emailLogRepository.AddRangeAsync(emailList);
await _emailRecipientLogRepository.AddRangeAsync(EmailRecipientLogList);
await _emailLogRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
return pageOutput;
}
// 取skip的值
@@ -236,19 +392,19 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
emailView.SenderName = fromMailbox.Name ?? string.Empty;
}
// 处理收件人
emailView.ToRecipients = message.To.Mailboxes.Select(address => new EmaliSendInfo
{
Name = address.Name ?? string.Empty,
Address = address.Address
}).ToList();
//// 处理收件人
//emailView.ToRecipients = message.To.Mailboxes.Select(address => new EmaliSendInfo
//{
// Name = address.Name ?? string.Empty,
// Address = address.Address
//}).ToList();
// 处理抄送人
emailView.CcRecipients = message.Cc.Mailboxes.Select(address => new EmaliSendInfo
{
Name = address.Name ?? string.Empty,
Address = address.Address
}).ToList();
//// 处理抄送人
//emailView.CcRecipients = message.Cc.Mailboxes.Select(address => new EmaliSendInfo
//{
// Name = address.Name ?? string.Empty,
// Address = address.Address
//}).ToList();
//// 处理密送人
//emailView.BccRecipients = message.Bcc.Mailboxes.Select(address => new EmaliSendInfo
@@ -12,7 +12,11 @@ namespace IRaCIS.Core.Application.Service
{
// 在此处拷贝automapper 映射
CreateMap<EmailLog, EmailLogView>();
CreateMap<EmailRecipientLog, EmailRecipientLogView>();
CreateMap<EmailLog, EmailLogView>()
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList));
CreateMap<EmailLog, GetEmailInfoOutDto>()
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList));
CreateMap<EmailLog, EmailLogAddOrEdit>().ReverseMap();
CreateMap<FrontAuditConfig, FrontAuditConfigAddOrEdit>().ReverseMap();