如何自动化向管理员发送多种表单邮件?泛型+AutoMapper方案是否可行?
你的泛型+AutoMapper方案完全可行,以下是具体实现步骤和验证
方案核心思路
通过泛型方法统一接收不同表单类型,借助AutoMapper将每种表单映射为包含Subject和Body的统一DTO,解耦表单类型与邮件内容生成逻辑,实现自动化发送。
具体实现步骤
1. 定义统一的邮件内容DTO
创建一个DTO承载邮件主题和正文,作为AutoMapper的目标类型:
public class EmailContentDto { public string Subject { get; set; } public string Body { get; set; } }
2. 配置AutoMapper映射规则
在AutoMapper配置类中,为每种表单类型配置对应的Subject和Body生成逻辑:
public class EmailMappingProfile : Profile { public EmailMappingProfile() { // FeedBackForm 映射规则 CreateMap<FeedBackForm, EmailContentDto>() .ForMember(dest => dest.Subject, opt => opt.MapFrom(src => $"Need consultation {src.Name}")) .ForMember(dest => dest.Body, opt => opt.MapFrom(src => $@"Name: {src.Name} Email: {src.Email} Phone: {src.PhoneNumber} Link: {src.BotLink}")); // ContactsForm 映射规则 CreateMap<ContactsForm, EmailContentDto>() .ForMember(dest => dest.Subject, opt => opt.MapFrom(src => $"Contact request from {src.FullName}")) .ForMember(dest => dest.Body, opt => opt.MapFrom(src => $@"Full Name: {src.FullName} Email: {src.ContactEmail} Message: {src.Message}")); } }
3. 修改EmailService为泛型实现
注入IMapper,将原有方法改为泛型,通过AutoMapper获取邮件内容后统一发送:
public class EmailService : IEmailService, ITransientService { private readonly IConfiguration _configuration; private readonly IMapper _mapper; public EmailService(IConfiguration configuration, IMapper mapper) { _configuration = configuration; _mapper = mapper; } public async Task SendFormToAdminEmailAsync<TForm>(TForm form) { // 映射表单到邮件内容DTO var emailContent = _mapper.Map<EmailContentDto>(form); if (emailContent == null || string.IsNullOrEmpty(emailContent.Subject) || string.IsNullOrEmpty(emailContent.Body)) { throw new InvalidOperationException($"未配置类型 {typeof(TForm).Name} 的邮件内容映射规则"); } var fromAddress = _configuration["EmailCredentials:Email"]; var fromPassword = _configuration["EmailCredentials:Password"]; var toAddress = new MailAddress("someAdminGmail@gmail.com"); using var mail = new MailMessage(new MailAddress(fromAddress), toAddress) { Subject = emailContent.Subject, Body = emailContent.Body }; using var smtp = new SmtpClient("smtp.gmail.com", 587) { Credentials = new NetworkCredential(fromAddress, fromPassword), EnableSsl = true }; await smtp.SendMailAsync(mail); } }
4. 额外优化建议
- 类型约束:如果所有表单都实现了共同接口(如
IFormWithContactInfo),可给泛型方法添加约束where TForm : IFormWithContactInfo,增强类型安全性。 - 模板解耦:将邮件正文模板移到配置文件或资源文件中,通过AutoMapper自定义解析逻辑读取模板并填充参数,进一步降低耦合。
- 异常处理:添加更细致的异常捕获与日志记录,方便排查发送失败问题。
方案验证结论
你的思路完全正确,这种实现方式:
- 实现了代码复用,新增表单时仅需添加AutoMapper映射规则,无需修改邮件发送核心逻辑
- 解耦了表单类型与邮件内容生成逻辑,符合开闭原则
- 代码结构清晰,易于维护和扩展
内容的提问来源于stack exchange,提问作者Kirill
相关产品推荐
相关产品推荐

