.NET Core 6中根据运行时条件实现邮件发送接口的最佳实践
.NET Core 6 动态邮件发送服务实现方案
针对你需要根据ProviderType运行时选择邮件发送服务的场景,工厂模式+依赖注入是最适配的方案,下面是具体实现步骤:
1. 定义核心契约与枚举
首先统一邮件发送的接口,以及支持的提供商类型:
// 邮件发送核心接口 public interface IEmailSender { Task SendEmailAsync(string toEmail, string subject, string body, bool isHtml = false); // 可根据需求扩展带附件、抄送等参数的重载 } // 提供商类型枚举 public enum EmailProviderType { Smtp, Imap, // 注:IMAP协议多用于接收邮件,发送建议用SMTP,此处按需求保留 SendGrid }
2. 实现各提供商的发送逻辑
每个提供商单独实现IEmailSender,各自处理对应协议/服务的发送逻辑:
SMTP实现
public class SmtpEmailSender : IEmailSender { private readonly SmtpSettings _settings; // 从配置注入SMTP参数 public SmtpEmailSender(IOptions<SmtpSettings> settings) { _settings = settings.Value; } public async Task SendEmailAsync(string toEmail, string subject, string body, bool isHtml = false) { var message = new MailMessage(_settings.FromEmail, toEmail) { Subject = subject, Body = body, IsBodyHtml = isHtml }; using var smtpClient = new SmtpClient(_settings.Host, _settings.Port) { Credentials = new NetworkCredential(_settings.UserName, _settings.Password), EnableSsl = _settings.EnableSsl }; await smtpClient.SendMailAsync(message); } } // SMTP配置模型 public class SmtpSettings { public string Host { get; set; } public int Port { get; set; } public string UserName { get; set; } public string Password { get; set; } public string FromEmail { get; set; } public bool EnableSsl { get; set; } }
SendGrid实现
先安装官方NuGet包:SendGrid
public class SendGridEmailSender : IEmailSender { private readonly SendGridSettings _settings; public SendGridEmailSender(IOptions<SendGridSettings> settings) { _settings = settings.Value; } public async Task SendEmailAsync(string toEmail, string subject, string body, bool isHtml = false) { var client = new SendGridClient(_settings.ApiKey); var from = new EmailAddress(_settings.FromEmail); var to = new EmailAddress(toEmail); var msg = MailHelper.CreateSingleEmail(from, to, subject, isHtml ? null : body, isHtml ? body : null); await client.SendEmailAsync(msg); } } // SendGrid配置模型 public class SendGridSettings { public string ApiKey { get; set; } public string FromEmail { get; set; } }
IMAP实现(仅作示例,实际发送建议用SMTP)
public class ImapEmailSender : IEmailSender { private readonly ImapSettings _settings; public ImapEmailSender(IOptions<ImapSettings> settings) { _settings = settings.Value; } public async Task SendEmailAsync(string toEmail, string subject, string body, bool isHtml = false) { // 此处根据IMAP发送逻辑实现,部分邮件服务器支持通过IMAP提交发送请求 // 实际项目中建议优先使用SMTP发送 throw new NotImplementedException("IMAP发送需结合具体邮件服务器实现"); } } public class ImapSettings { public string Host { get; set; } public int Port { get; set; } public string UserName { get; set; } public string Password { get; set; } }
3. 创建发送器工厂类
工厂类负责根据ProviderType动态返回对应的IEmailSender实例,利用.NET Core的DI容器管理实例生命周期:
public interface IEmailSenderFactory { IEmailSender GetEmailSender(EmailProviderType providerType); } public class EmailSenderFactory : IEmailSenderFactory { private readonly IServiceProvider _serviceProvider; public EmailSenderFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IEmailSender GetEmailSender(EmailProviderType providerType) { return providerType switch { EmailProviderType.Smtp => _serviceProvider.GetRequiredService<SmtpEmailSender>(), EmailProviderType.SendGrid => _serviceProvider.GetRequiredService<SendGridEmailSender>(), EmailProviderType.Imap => _serviceProvider.GetRequiredService<ImapEmailSender>(), _ => throw new ArgumentOutOfRangeException(nameof(providerType), "不支持的邮件提供商类型") }; } }
4. 注册服务到DI容器
在Program.cs中注册所有发送器、配置和工厂类:
var builder = WebApplication.CreateBuilder(args); // 注册配置 builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("SmtpSettings")); builder.Services.Configure<SendGridSettings>(builder.Configuration.GetSection("SendGridSettings")); builder.Services.Configure<ImapSettings>(builder.Configuration.GetSection("ImapSettings")); // 注册各邮件发送器 builder.Services.AddTransient<SmtpEmailSender>(); builder.Services.AddTransient<SendGridEmailSender>(); builder.Services.AddTransient<ImapEmailSender>(); // 注册工厂类 builder.Services.AddTransient<IEmailSenderFactory, EmailSenderFactory>(); // ...其他服务注册 var app = builder.Build(); // ...中间件配置 app.Run();
对应的appsettings.json配置示例:
{ "SmtpSettings": { "Host": "smtp.example.com", "Port": 587, "UserName": "your-email@example.com", "Password": "your-password", "FromEmail": "your-email@example.com", "EnableSsl": true }, "SendGridSettings": { "ApiKey": "your-sendgrid-api-key", "FromEmail": "your-email@example.com" }, "ImapSettings": { "Host": "imap.example.com", "Port": 993, "UserName": "your-email@example.com", "Password": "your-password" } }
5. 实际使用示例
在控制器或服务中注入IEmailSenderFactory,根据用户请求的ProviderType选择发送器:
[ApiController] [Route("api/email")] public class EmailController : ControllerBase { private readonly IEmailSenderFactory _senderFactory; public EmailController(IEmailSenderFactory senderFactory) { _senderFactory = senderFactory; } [HttpPost("send")] public async Task<IActionResult> SendEmail([FromBody] EmailRequest request) { var sender = _senderFactory.GetEmailSender(request.ProviderType); await sender.SendEmailAsync(request.ToEmail, request.Subject, request.Body, request.IsHtml); return Ok("邮件发送成功"); } } // 请求模型 public class EmailRequest { public EmailProviderType ProviderType { get; set; } public string ToEmail { get; set; } public string Subject { get; set; } public string Body { get; set; } public bool IsHtml { get; set; } = false; }
注意事项
- 若使用.NET 7+,可以用**键控服务(Keyed Services)**简化工厂逻辑,直接通过枚举作为键获取对应的
IEmailSender实现 - IMAP协议主要用于邮件接收,发送邮件优先选择SMTP或第三方服务(如SendGrid)
- 建议为每个发送器添加异常处理逻辑,比如捕获发送失败的异常并返回友好提示
内容的提问来源于stack exchange,提问作者James.mikael
相关产品推荐
相关产品推荐

