You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:40:28