c# - 作为启动配置过程的一部分,您如何发送电子邮件?
问题描述
作为此测试的一部分,我希望我的应用程序在首次启动并将启动电子邮件发送到某个位置时电子邮件凭据是否有效。
当我在启动甚至 SendGrid 中放置电子邮件功能时,如果凭据有效,则没有错误,但没有发送消息。我可以将其作为中间件过滤器的一部分和缓存的一部分来执行,但这实际上是我的首选,它实际上成为了一个作用域服务。
我的电子邮件代码作为控制器或服务调用的一部分工作,但即使在凭据有效的情况下它不会在启动时出错,但电子邮件实际上并没有发送。
启动.cs
public void ConfigureServices(IServiceCollection services)
{
var emailStatus = new EmailStatus();
try
{
_emailSender.SendEmailAsync(Options.Support, "App STARTUP",
$"email success.");
emailStatus.failed = false;
//Set
}
catch (SmtpCommandException ex)
{
_logger.LogError(ex.Message);
emailStatus.failed = false;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
// Debug.WriteLine("Exception: " + ex.Message);
_logger.LogError("Task Inner Exception: " + ex.InnerException);
_logger.LogError("Task StackTrace: " + ex.StackTrace);
emailStatus.failed = false;
}
services.AddSingleton(emailStatus);
}
电子邮件发件人.cs
public class EmailSender : IEmailSender
{
public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor)
{
Options = optionsAccessor.Value;
}
public EmailSender(AuthMessageSenderOptions options)
{
this.Options = options;
}
public AuthMessageSenderOptions Options { get; } //set only via Secret Manager
public Task SendEmailAsync(string email, string subject, string message)
{
return Execute(subject, message, email);
}
public async Task Execute(string subject, string message, string email)
{
if (Options.Service != "SendGrid")
{
var mailMessage = new MimeMessage();
mailMessage.To.Add(new MailboxAddress(email));
mailMessage.From.Add(new MailboxAddress("noreply@email.com"));
mailMessage.Subject = subject;
mailMessage.Body = new TextPart(TextFormat.Html)
{
Text = message
};
// mailMessage.Body = message;
//Be careful that the SmtpClient class is the one from Mailkit not the framework!
using (var emailClient = new SmtpClient())
{
//The last parameter here is to use SSL (Which you should!)
await emailClient.ConnectAsync(Options.Domain, Options.Port, true);
//Remove any OAuth functionality as we won't be using it.
emailClient.AuthenticationMechanisms.Remove("XOAUTH2");
emailClient.Authenticate(Options.SendGridUser, Options.SendGridKey);
try
{
await emailClient.SendAsync(mailMessage).ConfigureAwait(false);
await emailClient.DisconnectAsync(true).ConfigureAwait(false);
}
catch (Exception ex)
{
await emailClient.DisconnectAsync(true).ConfigureAwait(false);
throw ex;
// return BadRequest(new { message = "Email failed to send", error = ex.ToString() });
// Label1.Text = ex.ToString();
}
// emailClient.Disconnect(true);
}
}
else
{
var client = new SendGridClient(Options.SendGridKey);
var msg = new SendGridMessage()
{
From = new EmailAddress("noreply@email.com", "Do Not Reply"),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(email));
// Disable click tracking.
// See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
await client.SendEmailAsync(msg);
}
}
}
解决方案
考虑使用一个IHostedService
创建将作为启动过程的一部分启动的托管服务
public class StartupEmailHostedService : IHostedService {
private readonly IEmailSender emailSender;
private readonly ILogger logger;
private EmailStatus emailStatus;
public StartupEmailHostedService(IEmailSender emailSender, EmailStatus emailStatus, ILogger<StartupEmailHostedService> logger) {
this.services = services;
this.logger = logger;
this.emailStatus = emailStatus;
}
public async Task StartAsync(CancellationToken cancellationToken) {
try {
await emailSender.SendEmailAsync(Options.Support, "App STARTUP", $"email success.");
emailStatus.failed = false;
} catch (SmtpCommandException ex) {
logger.LogError(ex.Message);
emailStatus.failed = true;
} catch (Exception ex) {
logger.LogError(ex.Message);
logger.LogError("Task Inner Exception: " + ex.InnerException);
logger.LogError("Task StackTrace: " + ex.StackTrace);
emailStatus.failed = true;
};
}
public Task StopAsync(CancellationToken cancellationToken) {
return Task.CompletedTask;
}
}
现在确保在启动时将所有内容都注册到服务集合中。
public void ConfigureServices(IServiceCollection services) {
//...assuming other dependencies
services.AddTransient<IEmailSender, EmailSender>();
services.AddSingleton<EmailStatus>();
services.AddHostedService<StartupEmailHostedService>();
}
当托管服务启动时,将调用电子邮件逻辑以及所需的功能。
尝试在 Startup 中处理所有这些横切关注点是不必要的,并且可能会导致启动本身出现问题,因为它只是充当引导程序并连接应用程序执行其功能所需的内容。
推荐阅读
- vue.js - Vue.js 的基本结构组件问题
- bash - 删除名称与字符串匹配的文件除外
- r - R - 使用 dplyr 根据每列的分位数过滤每列
- node.js - 是否可以使用 Testcafe 检查 E2E 测试中的预期颜色代码?
- javascript - 如何在接收数据时进行渲染(在一个路由挂载中多次渲染)
- javascript - 为每一行动态获取文本字段值 onblur()
- python-3.x - Python - 缩进错误,但不是来自混合制表符和空格
- d3.js - D3 - 堆积条形图,在工具提示中显示所有值
- vba - VBA学习代码,找词,考虑下一列,如果然后
- angular - 添加逻辑是否添加标头到 Angular HttpInterceptor 中的 req.clone