我认为遵循框架而不是“反对它”总是好的。我并不是说其他答案是错误的,它们都是围绕基本方法调用包装器,有时会在出现问题时抑制堆栈。
看看我的扩展方法
public static class SMTPLoggerExtensionMethods
{
class MailData
{
public MailData(EMailRoles role, string subject,string body, bool isHtml)
{
this.Roles = role;
this.Subject = subject;
this.Body = body;
this.IsHtml = isHtml;
}
public EMailRoles Roles { get; }
public string Subject { get; }
public string Body { get; }
public bool IsHtml { get; }
}
/// <summary>
/// Send an email to all users defined in the email configuration of the IFireWall using a non-blocking method
/// </summary>
/// <param name="fireWall">The firewall instance</param>
/// <param name="roles">The roles that are to be send the email</param>
/// <param name="subject">the subject for the email</param>
/// <param name="body">the email body</param>
/// <param name="isHtml">indicating the email is HTML formated </param>
public static void SendEmail(this IFireWall fireWall, EMailRoles roles, string subject, string body, bool isHtml)
{
var state = new MailData(roles, subject, body, isHtml);
System.Threading.ThreadPool.QueueUserWorkItem(PSendMail, state);
}
private static void PSendMail(object? state)
{
if (state is MailData mail)
{
var smtp = DIContainer.GetDefaultInstanceOrNull<SMTPMailLogger>();
smtp?.Enqueue(mail.Roles, mail.Subject, mail.Body, mail.IsHtml);
}
}
}
无法保证会发送电子邮件,也不会将错误填充回调用者,但是作为向给定组的所有用户发送电子邮件的非阻塞方法......为什么不呢。向给定组中的所有用户发送电子邮件时没有错误且响应缓慢,这可能适合您的用例。
然后我将调用扩展方法,如下面的控制器示例所示。
没有阻塞,在我的情况下,如果我们错过了一封电子邮件,也没有压力,因为日志包含用户体验良好的错误......只是真正在看日志的人 ;-)
[BlockDuration(seconds: 60, sliding: true, doubleDurationPerIncident: true)]
public class HomeController : Controller
{
private readonly IFireWall _fireWall;
private readonly IPageRequest _page;
private ILatLongRepository _latLongRepository;
public HomeController(IFireWall fireWall, IPageRequest page, ILatLongRepository latLongRepository)
{
_page = page;
_fireWall = fireWall;
_latLongRepository = latLongRepository;
}
[GeoIgnore(maxRequest: 5)]
[Ignore(skip: FireWallGuardModules.RejectPenetrationAttempts
| FireWallGuardModules.RejectRepeatViolations
| FireWallGuardModules.RejectWrongUserType
, skipCount: 5)]
public IActionResult Blocked(BlockingReason id)
{
//call the extension method here
_fireWall.SendEmail(roles: Walter.Web.FireWall.Destinations.Email.EMailRoles.SecurityRelevant | Walter.Web.FireWall.Destinations.Email.EMailRoles.FireWallAdministrationViolations
, subject: $"Access to {_page.OriginalUrl} rejected for user in {_latLongRepository.QueryMapLocation(_page.IPAddress)}"
, body: MailUtils.MakeMailBodyForBlcokedUser(page: _page)
, isHtml: true
);
if (_page.User.AsFirewallUser().UserType.HasFlag(UserTypes.IsMalicious))
{
return View("_Malicious", id);
}
return View(id);
}
}