using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using MailKit; using Medallion.Threading; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Options; using MimeKit; namespace IRaCIS.Core.Application.Service { public interface IMailVerificationService { Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode); Task SendEmailVerification(string emailAddress, int verificationCode); Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login); Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode); Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode); Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl); Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456"); Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl); Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl); Task DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl); Task UserFeedBackMail(Guid feedBackId); } public class MailVerificationService(IRepository _verificationCodeRepository, IRepository _systemBasicDatarepository, IRepository _visitTaskRepository, IRepository _trialSiteRepository, IRepository _userRoleRepository, IRepository _identityUserRepository, IRepository _userFeedBackRepository, ITokenService _tokenService, IRepository _subjectVisitRepository, IRepository _trialRepository, IRepository _userTypeRepository, IRepository _doctorTypeRepository, IRepository _dictionaryRepository, IRepository _emailNoticeConfigrepository, IOptionsMonitor systemEmailConfig, IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IMailVerificationService { private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; private async Task GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend, Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc) { var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync(); if (configInfo == null) { throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息,请联系运维人员核查"); } var (topicStr, htmlBodyStr) = _userInfo.IsEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN); try { //每个场景修改主题 和body的逻辑不一样 (topicStr, htmlBodyStr) = emailFunc((topicStr, htmlBodyStr)); } catch (Exception ex) { throw new BusinessValidationFailedException("邮件模板内容有误,填充内容出现问题,请联系运维人员核查"); } messageToSend.Subject = topicStr; var builder = new BodyBuilder(); builder.HtmlBody = htmlBodyStr; messageToSend.Body = builder.ToMessageBody(); return configInfo; } public async Task GetEmailConfigInfoAsync(EmailBusinessScenario scenario) { var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).Include(t => t.EmailNoticeUserTypeList).FirstOrDefaultAsync(); if (configInfo == null) { throw new BusinessValidationFailedException("系统未找到当前场景邮件配置信息,请联系运维人员核查"); } return configInfo; } private EventHandler GetEmailSuccessHandle(Guid userId, int verificationCode, string email = "") { EventHandler sucessHandle = (sender, args) => { // args.Response var code = verificationCode.ToString(); _ = _verificationCodeRepository.AddAsync(new VerificationCode() { CodeType = VerifyType.Email, HasSend = true, Code = code, UserId = userId, EmailOrPhone = email, ExpirationTime = DateTime.Now.AddMinutes(3) }).Result; _ = _verificationCodeRepository.SaveChangesAsync().Result; }; return sucessHandle; } private string ReplaceCompanyName(string needDealtxt) { var str = needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN) .Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN); return str; } //MFA public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login) { var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(userName, emailAddress)); //主题---[来自{0}] 关于MFA邮箱验证的提醒 var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userName, verificationCode ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc); var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle); } /// /// Reviewer简历录入 发送验证码 /// /// /// /// public async Task SendEmailVerification(string emailAddress, int verificationCode) { var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress)); //主题 //---[来自展影IRC]的提醒 var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), "Sir/Madam", //---您正在参与展影医疗IRC项目 companyName, verificationCode ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc); //此时不知道用户 var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle); } //中心调研 登陆 public async Task AnolymousSendEmail(string researchProgramNo, string emailAddress, int verificationCode) { var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress)); //主题 //$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒"; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName, researchProgramNo); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), "Sir/Madam", //---您正在参与展影医疗IRC项目中心调研工作 companyName, verificationCode ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc); //此时不知道用户 var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle); } #region 邮件已修改 //添加用户发送邮件 public async Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl) { var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail)); //主题 //---[来自展影IRC] 关于创建账户的提醒 var token = _tokenService.GetToken(new UserTokenInfo() { UserRoleId = sysUserInfo.Id }); await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new IdentityUser() { EmailToken = token }); routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), sysUserInfo.FullName, sysUserInfo.UserName, string.Join(',', sysUserInfo.UserRoleList.Select(t => t.UserTypeRole.UserTypeShortName)), redirectUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } //管理员重置密码发送邮件 public async Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456") { var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail)); //主题 //---[来自展影IRC] 关于重置账户密码的提醒 var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), sysUserInfo.FullName, sysUserInfo.UserName, string.Join(',', sysUserInfo.UserRoleList.Select(t => t.UserTypeRole.UserTypeShortName)), pwdNotMd5 ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } //用户重置邮箱 public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode) { var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(userName, emailAddress)); //主题 //---[来自展影IRC] 关于重置邮箱的提醒 var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userName, //---您正在进行邮箱重置操作 verificationCode ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc); var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle); } //不登录 通过邮箱重置密码 public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode) { var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress)); var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), "Sir/Madam", //---您正在进行邮箱重置密码操作 verificationCode ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc); ////此时不知道用户 var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, sucessHandle); } #endregion //Site调研 用户加入项目 public async Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl) { var sysUserInfo = (await _userRoleRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail)); //主题 // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信"; var token = _tokenService.GetToken(new UserTokenInfo() { UserRoleId = sysUserInfo.Id }); if (sysUserInfo.IsFirstAdd) { await _userRoleRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new UserRole() { EmailToken = token }); } var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), sysUserInfo.FullName, trialInfo.ExperimentName, trialInfo.ResearchProgramNo, trialInfo.TrialCode, sysUserInfo.UserName, sysUserInfo.UserTypeRole.UserTypeShortName, sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } //外部用户 加入项目 public async Task ExternalUserJoinEmail(Guid trialId, Guid userId, string baseUrl, string rootUrl) { var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId)).IfNullThrowException(); var sysUserInfo = (await _userRoleRepository.Where(t => t.Id == userId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(String.Empty, sysUserInfo.EMail)); //主题 // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信"; var token = _tokenService.GetToken(new UserTokenInfo() { UserRoleId = sysUserInfo.Id }); if (sysUserInfo.IsFirstAdd) { await _userRoleRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new UserRole() { EmailToken = token }); } var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + sysUserInfo.UserTypeRole.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), sysUserInfo.FullName, trialInfo.ExperimentName, trialInfo.ResearchProgramNo, trialInfo.TrialCode, sysUserInfo.UserName, sysUserInfo.UserTypeRole.UserTypeShortName, sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null); } //医生生成账号加入 或者已存在账号加入到项目中 public async Task DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl) { var doctor = await _doctorTypeRepository.FindAsync(doctorId); UserRole sysUserInfo = new UserRole(); var userType = await _userTypeRepository.FirstAsync(t => t.UserTypeEnum == UserTypeEnum.IndependentReviewer); var @lock = _distributedLockProvider.CreateLock($"UserCode"); using (await @lock.AcquireAsync()) { var isDoctorHaveAccount = await _userRoleRepository.AnyAsync(t => t.DoctorId == doctorId); if (!isDoctorHaveAccount) { var saveItem = new UserRole() { FirstName = doctor.FirstName, LastName = doctor.LastName, EMail = doctor.EMail }; var trialType = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialType).FirstOrDefaultAsync(); if (trialType == TrialType.NoneOfficial) { saveItem.IsTestUser = true; } saveItem.Code = _userRoleRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(UserRole)); saveItem.UserName = saveItem.UserCode; saveItem.UserTypeEnum = UserTypeEnum.IndependentReviewer; saveItem.DoctorId = doctorId; saveItem.UserTypeId = userType.Id; var savedUser = await _userRoleRepository.AddAsync(saveItem); //下面获取Token 需要这部分信息 sysUserInfo = savedUser.Clone(); sysUserInfo.UserTypeRole = userType; await _userRoleRepository.SaveChangesAsync(); } else { sysUserInfo = (await _userRoleRepository.Where(t => t.DoctorId == doctorId).Include(t => t.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException(); } } var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); //收件地址 messageToSend.To.Add(new MailboxAddress(doctor.FullName, doctor.EMail)); var token = _tokenService.GetToken(new UserTokenInfo() { UserRoleId = sysUserInfo.Id }); if (sysUserInfo.IsFirstAdd) { await _userRoleRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new UserRole() { EmailToken = token }); } var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&UserType=" + userType.UserTypeShortName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token; var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login")); var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}"; //主题 // $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信"; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), sysUserInfo.FullName, trialInfo.ExperimentName, trialInfo.ResearchProgramNo, trialInfo.TrialCode, sysUserInfo.UserName, userType.UserTypeShortName, sysUserInfo.IsFirstAdd ? redirectUrl : baseUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null); return sysUserInfo.Id; } //用户反馈邮件 public async Task UserFeedBackMail(Guid feedBackId) { var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUserRole).ThenInclude(t => t.UserTypeRole).FirstNotNullAsync(); var messageToSend = new MimeMessage(); //发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); var isHaveTrialId = feedBack.TrialId != null; var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN; var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack)); var emailConfigInfo = await GetEmailConfigInfoAsync(emialScenario); var userTypeEnumList = emailConfigInfo.EmailNoticeUserTypeList.Where(t => t.EmailUserType == EmailUserType.To).Select(t => t.UserType).ToList(); var emailList = await _userRoleRepository.Where(t => userTypeEnumList.Contains(t.UserTypeEnum) && (isHaveTrialId ? t.UserTrials.Any(t => t.TrialId == feedBack.TrialId) : true)).Select(t => new { t.EMail, t.UserTypeEnum, t.FullName }).ToListAsync(); foreach (var email in emailList) { messageToSend.To.Add(new MailboxAddress(email.FullName, email.EMail)); } var userNames = string.Join(',', emailList.Select(t => t.FullName)); //影像阅片反馈 pm if (feedBack.VisitTaskId != null) { var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.IRImageError).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync(); Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userNames, info.TrialCode, info.SubejctCode, info.VisitName, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.FullName, emailType, feedBack.QuestionDescription, _systemEmailConfig.SiteUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc); } else if (feedBack.SubjectVisitId != null) { var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync(); Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userNames, info.TrialCode, info.SubejctCode, info.VisitName, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.FullName, emailType, feedBack.QuestionDescription, _systemEmailConfig.SiteUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc); } //项目相关的反馈 pm admin else if (feedBack.TrialId != null) { var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync(); var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync(); Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, info.ResearchProgramNo); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userNames, info.TrialCode, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.FullName, emailType, feedBack.QuestionDescription, _systemEmailConfig.SiteUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc); } //项目无关的反馈 admin else { Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), userNames, feedBack.CreateUserRole.UserTypeRole.UserTypeShortName, feedBack.CreateUserRole.FullName, feedBack.QuestionDescription, _systemEmailConfig.SiteUrl ); return (topicStr, htmlBodyStr); }; await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc); } await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } } }