修改
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
5716c4169a
commit
7b243a9615
|
|
@ -1259,6 +1259,128 @@
|
||||||
裁决日期 CODTC
|
裁决日期 CODTC
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto">
|
||||||
|
<summary>
|
||||||
|
公共影像导表基类(IVUS / OCT 通用)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.ResearchProgramNo">
|
||||||
|
<summary>研究标识符</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.TrialSiteCode">
|
||||||
|
<summary>中心编号</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.SubjectCode">
|
||||||
|
<summary>受试者标识符</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.USUBJID">
|
||||||
|
<summary>受试者唯一标识</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.VisitName">
|
||||||
|
<summary>访视名称</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.ArmEnum">
|
||||||
|
<summary>阅片人角色</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.LatestScanDate">
|
||||||
|
<summary>拍片日期</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.SignTime">
|
||||||
|
<summary>阅片完成时间</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.VisitNum">
|
||||||
|
<summary>
|
||||||
|
访视编号 VISITNUM
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IVUS_OCTBaseDto.VisitNote">
|
||||||
|
<summary>访视点备注</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.Service.Common.IvusExportDto">
|
||||||
|
<summary>
|
||||||
|
IVUS 导表模型
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.TARGETV">
|
||||||
|
<summary>靶段</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.PLAQUE">
|
||||||
|
<summary>斑块编号</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.EEM">
|
||||||
|
<summary>外弹力膜面积</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.LUMEN">
|
||||||
|
<summary>管腔面积</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.PA">
|
||||||
|
<summary>外弹力膜与管腔面积差值</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.PFC">
|
||||||
|
<summary>回撤中的图像帧数</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.FC">
|
||||||
|
<summary>分析图像帧数</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.TOTALEEM">
|
||||||
|
<summary>总外弹力膜面积 (如无可不填)</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.TOTALPA">
|
||||||
|
<summary>总 PA (如无可不填)</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.IvusExportDto.PAV">
|
||||||
|
<summary>PAV (如无可不填)</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:IRaCIS.Core.Application.Service.Common.OctExportDto">
|
||||||
|
<summary>
|
||||||
|
OCT 导表模型
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.TARGETV">
|
||||||
|
<summary>靶段</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.PLAQUE">
|
||||||
|
<summary>斑块编号</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.TestID">
|
||||||
|
<summary>测量标识</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.TESTCD">
|
||||||
|
<summary>测量参数名称</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.ORRES">
|
||||||
|
<summary>测量参数值</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.ORRESU">
|
||||||
|
<summary>测量值单位</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.PLATYPE">
|
||||||
|
<summary>斑块类型</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.MINFCT">
|
||||||
|
<summary>最小纤维帽厚度</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.AVGMFCT">
|
||||||
|
<summary>平均纤维帽厚度</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.LAMEAN">
|
||||||
|
<summary>脂质角度平均值</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.LAMAX">
|
||||||
|
<summary>脂质角度最大值</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.MACRI">
|
||||||
|
<summary>巨噬细胞浸润</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.MIARC">
|
||||||
|
<summary>巨噬细胞浸润角度</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.MC">
|
||||||
|
<summary>微通道</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:IRaCIS.Core.Application.Service.Common.OctExportDto.CCS">
|
||||||
|
<summary>胆固醇结晶</summary>
|
||||||
|
</member>
|
||||||
<member name="P:IRaCIS.Core.Application.Service.Common.TUValueEnum.TUValueType">
|
<member name="P:IRaCIS.Core.Application.Service.Common.TUValueEnum.TUValueType">
|
||||||
<summary>
|
<summary>
|
||||||
取值类型 TUSPID
|
取值类型 TUSPID
|
||||||
|
|
@ -1374,35 +1496,6 @@
|
||||||
<param name="message"></param>
|
<param name="message"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.ExtractErrorMessage(MimeKit.MimeMessage)">
|
|
||||||
<summary>
|
|
||||||
从失败通知邮件中提取错误信息
|
|
||||||
</summary>
|
|
||||||
<param name="message"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.GetContentSummary(System.String)">
|
|
||||||
<summary>
|
|
||||||
获取邮件内容摘要(前200个字符)
|
|
||||||
</summary>
|
|
||||||
<param name="content"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.ProcessFailureNotificationByRecipient(MimeKit.MimeMessage)">
|
|
||||||
<summary>
|
|
||||||
通过收件人信息处理失败通知邮件
|
|
||||||
</summary>
|
|
||||||
<param name="message"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.IsLikelyRelatedEmail(MimeKit.MimeMessage,IRaCIS.Core.Domain.Models.EmailLog)">
|
|
||||||
<summary>
|
|
||||||
判断失败通知邮件是否与指定的EmailLog相关
|
|
||||||
</summary>
|
|
||||||
<param name="failureMessage"></param>
|
|
||||||
<param name="emailLog"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.BuildSearchQuery(IRaCIS.Core.Application.ViewModel.EmailLogQuery)">
|
<member name="M:IRaCIS.Core.Application.Service.EmailLogService.BuildSearchQuery(IRaCIS.Core.Application.ViewModel.EmailLogQuery)">
|
||||||
<summary>
|
<summary>
|
||||||
邮件筛选条件构建
|
邮件筛选条件构建
|
||||||
|
|
@ -18171,7 +18264,7 @@
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetSiteSurveyInfo(System.Guid,System.Guid)">
|
<member name="M:IRaCIS.Core.Application.Contracts.TrialSiteSurveyService.GetSiteSurveyInfo(System.Nullable{System.Guid},System.Guid)">
|
||||||
<summary>
|
<summary>
|
||||||
直接查询相关所有数据
|
直接查询相关所有数据
|
||||||
</summary>
|
</summary>
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
// 第二步:处理收件箱中的邮件发送失败通知
|
// 第二步:处理收件箱中的邮件发送失败通知
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ProcessInboxFailureNotifications();
|
await ProcessInboxFailureNotifications(startDate);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -488,7 +488,7 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
/// 处理收件箱中的邮件发送失败通知
|
/// 处理收件箱中的邮件发送失败通知
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task ProcessInboxFailureNotifications()
|
public async Task ProcessInboxFailureNotifications(DateTime startTime)
|
||||||
{
|
{
|
||||||
using (var client = new ImapClient())
|
using (var client = new ImapClient())
|
||||||
{
|
{
|
||||||
|
|
@ -508,7 +508,7 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
.Or(SearchQuery.BodyContains("失败"))
|
.Or(SearchQuery.BodyContains("失败"))
|
||||||
.Or(SearchQuery.BodyContains("错误"))
|
.Or(SearchQuery.BodyContains("错误"))
|
||||||
.Or(SearchQuery.BodyContains("undeliverable"))
|
.Or(SearchQuery.BodyContains("undeliverable"))
|
||||||
.Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(DateTime.Parse("2025-11-27")));
|
.Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(startTime));
|
||||||
|
|
||||||
var uids = inboxFolder.Search(searchQuery).ToList();
|
var uids = inboxFolder.Search(searchQuery).ToList();
|
||||||
var processedCount = 0;
|
var processedCount = 0;
|
||||||
|
|
@ -529,42 +529,31 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
.Where(x => x.MessageId == originalMessageId)
|
.Where(x => x.MessageId == originalMessageId)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (emailLog != null && emailLog.EmailStateEnum == EmailState.Success)
|
await _emailLogRepository.BatchUpdateNoTrackingAsync(x => x.MessageId == originalMessageId, x => new EmailLog()
|
||||||
{
|
{
|
||||||
// 提取错误信息
|
EmailStateEnum = EmailState.Error,
|
||||||
var errorMessage = ExtractErrorMessage(message);
|
ErrorInfo = message.TextBody
|
||||||
|
|
||||||
// 更新邮件状态为失败
|
});
|
||||||
emailLog.EmailStateEnum = EmailState.Error;
|
|
||||||
emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
|
|
||||||
|
|
||||||
//await _emailLogRepository.UpdateAsync(emailLog);
|
updatedCount++;
|
||||||
updatedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果无法从Message-Id匹配,尝试从邮件内容中提取收件人信息进行匹配
|
|
||||||
await ProcessFailureNotificationByRecipient(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processedCount++;
|
processedCount++;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"处理收件箱邮件 UID:{uid} 失败: {ex.Message}");
|
|
||||||
// 记录详细异常信息用于调试
|
|
||||||
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"收件箱失败通知邮件处理完成: 共处理 {processedCount} 封邮件,更新 {updatedCount} 条记录");
|
|
||||||
inboxFolder.Close();
|
inboxFolder.Close();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"连接收件箱处理失败通知邮件时出错: {ex.Message}");
|
Console.WriteLine($"连接收件箱处理失败通知邮件时出错: {ex.Message}");
|
||||||
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
|
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
|
||||||
throw; // 重新抛出异常,让上层调用者决定如何处理
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -599,7 +588,48 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
return originalMessageId;
|
return originalMessageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果邮件头中没有,尝试从邮件正文中提取
|
// 检查邮件附件中是否包含.eml文件(这是最常见的失败通知格式)
|
||||||
|
foreach (var attachment in message.Attachments)
|
||||||
|
{
|
||||||
|
if (attachment is MessagePart messagePart)
|
||||||
|
{
|
||||||
|
// 直接获取嵌入的邮件消息
|
||||||
|
var originalMessageIdFromAttachment = messagePart.Message?.MessageId;
|
||||||
|
if (!string.IsNullOrEmpty(originalMessageIdFromAttachment))
|
||||||
|
{
|
||||||
|
return originalMessageIdFromAttachment.Trim('<', '>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attachment is MimePart mimePart)
|
||||||
|
{
|
||||||
|
// 检查文件扩展名是否为.eml
|
||||||
|
var fileName = mimePart.FileName ?? mimePart.ContentType.Name;
|
||||||
|
if (!string.IsNullOrEmpty(fileName) &&
|
||||||
|
(fileName.EndsWith(".eml", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
mimePart.ContentType.MimeType.Equals("message/rfc822", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 解析.eml附件内容
|
||||||
|
using var memoryStream = new MemoryStream();
|
||||||
|
mimePart.Content.DecodeTo(memoryStream);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
var originalMessage = MimeMessage.Load(memoryStream);
|
||||||
|
if (!string.IsNullOrEmpty(originalMessage?.MessageId))
|
||||||
|
{
|
||||||
|
return originalMessage.MessageId.Trim('<', '>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"解析.eml附件时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果邮件头和附件中都没有,尝试从邮件正文中提取
|
||||||
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
||||||
|
|
||||||
// 尝试匹配常见的Message-Id格式
|
// 尝试匹配常见的Message-Id格式
|
||||||
|
|
@ -621,129 +651,6 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从失败通知邮件中提取错误信息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string ExtractErrorMessage(MimeMessage message)
|
|
||||||
{
|
|
||||||
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
|
||||||
|
|
||||||
// 尝试提取具体的错误信息
|
|
||||||
// 常见的错误信息模式
|
|
||||||
var errorPatterns = new[]
|
|
||||||
{
|
|
||||||
@"(?i)reason\s*:\s*([^\r\n]+)",
|
|
||||||
@"(?i)error\s*:\s*([^\r\n]+)",
|
|
||||||
@"(?i)failure\s*:\s*([^\r\n]+)",
|
|
||||||
@"(?i)诊断信息[::]\s*([^\r\n]+)",
|
|
||||||
@"(?i)错误详情[::]\s*([^\r\n]+)",
|
|
||||||
@"(?i)Technical details of permanent failure[::]\s*([^\r\n]+)",
|
|
||||||
@"(?i)The error that the other server returned was[::]\s*([^\r\n]+)"
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var pattern in errorPatterns)
|
|
||||||
{
|
|
||||||
var match = System.Text.RegularExpressions.Regex.Match(content, pattern);
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
return match.Groups[1].Value.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有找到具体的错误信息,返回邮件主题和部分内容
|
|
||||||
return $"主题: {message.Subject}\n内容摘要: {GetContentSummary(content)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取邮件内容摘要(前200个字符)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string GetContentSummary(string content)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(content))
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
// 移除HTML标签
|
|
||||||
var plainText = System.Text.RegularExpressions.Regex.Replace(content, @"<[^>]+>", string.Empty);
|
|
||||||
plainText = System.Text.RegularExpressions.Regex.Replace(plainText, @"\s+", " ");
|
|
||||||
|
|
||||||
return plainText.Length > 200 ? plainText.Substring(0, 200) + "..." : plainText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 通过收件人信息处理失败通知邮件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task ProcessFailureNotificationByRecipient(MimeMessage message)
|
|
||||||
{
|
|
||||||
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
|
||||||
|
|
||||||
// 尝试从邮件内容中提取原始收件人地址
|
|
||||||
var recipientPattern = @"(?:to|To|收件人)[::]\s*([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})";
|
|
||||||
var match = System.Text.RegularExpressions.Regex.Match(content, recipientPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
var recipientEmail = match.Groups[1].Value;
|
|
||||||
|
|
||||||
// 查找最近发送给该收件人的邮件
|
|
||||||
var recentEmailLogs = await _emailLogRepository
|
|
||||||
.Where(x => x.EmailRecipientLogList.Any(r => r.RecipientAddress == recipientEmail))
|
|
||||||
.Where(x => x.EmailDate >= DateTime.Now.AddDays(-7)) // 最近7天内的邮件
|
|
||||||
.OrderByDescending(x => x.EmailDate)
|
|
||||||
.Take(5) // 取最近的5封
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
foreach (var emailLog in recentEmailLogs)
|
|
||||||
{
|
|
||||||
if (emailLog.EmailStateEnum == EmailState.Success)
|
|
||||||
{
|
|
||||||
// 检查邮件主题是否匹配(如果失败通知邮件中包含原始主题)
|
|
||||||
if (IsLikelyRelatedEmail(message, emailLog))
|
|
||||||
{
|
|
||||||
var errorMessage = ExtractErrorMessage(message);
|
|
||||||
emailLog.EmailStateEnum = EmailState.Error;
|
|
||||||
emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
|
|
||||||
//await _emailLogRepository.UpdateAsync(emailLog);
|
|
||||||
break; // 找到匹配的就停止
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断失败通知邮件是否与指定的EmailLog相关
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="failureMessage"></param>
|
|
||||||
/// <param name="emailLog"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private bool IsLikelyRelatedEmail(MimeMessage failureMessage, EmailLog emailLog)
|
|
||||||
{
|
|
||||||
var failureContent = failureMessage.HtmlBody ?? failureMessage.TextBody ?? failureMessage.Subject ?? string.Empty;
|
|
||||||
var emailSubject = emailLog.EmailSubject ?? string.Empty;
|
|
||||||
|
|
||||||
// 检查主题是否包含在失败通知中
|
|
||||||
if (!string.IsNullOrEmpty(emailSubject) &&
|
|
||||||
failureContent.Contains(emailSubject, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查发件人是否匹配
|
|
||||||
if (!string.IsNullOrEmpty(emailLog.SenderAddress) &&
|
|
||||||
(failureContent.Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
failureMessage.From.ToString().Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//private string AcquireOAuth2TokenByPassword()
|
//private string AcquireOAuth2TokenByPassword()
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
{
|
{
|
||||||
Task<IResponseOutput> AddOrUpdateTrialSiteSurvey(TrialSiteSurveyAddOrEdit addOrEditTrialSiteSurvey);
|
Task<IResponseOutput> AddOrUpdateTrialSiteSurvey(TrialSiteSurveyAddOrEdit addOrEditTrialSiteSurvey);
|
||||||
//Task<IResponseOutput> DeleteTrialSiteSurvey(Guid trialSiteSurveyId);
|
//Task<IResponseOutput> DeleteTrialSiteSurvey(Guid trialSiteSurveyId);
|
||||||
Task<LoginReturnDTO> GetSiteSurveyInfo(Guid trialSiteSurveyId, Guid trialId);
|
Task<LoginReturnDTO> GetSiteSurveyInfo(Guid? trialSiteSurveyId, Guid trialId);
|
||||||
Task<PageOutput<TrialSiteSurveyView>> GetTrialSiteSurveyList(TrialSiteSurveyQueryDTO surveyQueryDTO);
|
Task<PageOutput<TrialSiteSurveyView>> GetTrialSiteSurveyList(TrialSiteSurveyQueryDTO surveyQueryDTO);
|
||||||
Task<TrialSurveyInitInfo> GetTrialSurveyInitInfo(Guid trialId);
|
Task<TrialSurveyInitInfo> GetTrialSurveyInitInfo(Guid trialId);
|
||||||
Task<IResponseOutput> SendVerifyCode(SiteSurveySendVerifyCode userInfo);
|
Task<IResponseOutput> SendVerifyCode(SiteSurveySendVerifyCode userInfo);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ public class EmailLog : BaseFullAuditEntity
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 错误信息
|
/// 错误信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[StringLength(5000)]
|
||||||
public string ErrorInfo { get; set; }
|
public string ErrorInfo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -58,8 +59,6 @@ public class EmailLog : BaseFullAuditEntity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EmailState EmailStateEnum { get; set; }
|
public EmailState EmailStateEnum { get; set; }
|
||||||
|
|
||||||
[StringLength(5000)]
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 邮件内容
|
/// 邮件内容
|
||||||
|
|
|
||||||
21265
IRaCIS.Core.Infra.EFCore/Migrations/20251128060451_ErrorInfo.Designer.cs
generated
Normal file
21265
IRaCIS.Core.Infra.EFCore/Migrations/20251128060451_ErrorInfo.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,50 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Infra.EFCore.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class ErrorInfo : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ErrorMessage",
|
||||||
|
table: "EmailLog");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "ErrorInfo",
|
||||||
|
table: "EmailLog",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
maxLength: 5000,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(400)",
|
||||||
|
oldMaxLength: 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "ErrorInfo",
|
||||||
|
table: "EmailLog",
|
||||||
|
type: "nvarchar(400)",
|
||||||
|
maxLength: 400,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)",
|
||||||
|
oldMaxLength: 5000);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "ErrorMessage",
|
||||||
|
table: "EmailLog",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
maxLength: 5000,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2396,11 +2396,6 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
|
||||||
.HasColumnType("nvarchar(400)");
|
.HasColumnType("nvarchar(400)");
|
||||||
|
|
||||||
b.Property<string>("ErrorInfo")
|
b.Property<string>("ErrorInfo")
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(400)
|
|
||||||
.HasColumnType("nvarchar(400)");
|
|
||||||
|
|
||||||
b.Property<string>("ErrorMessage")
|
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(5000)
|
.HasMaxLength(5000)
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue