I think it's always good to go with the framework and not to "go against it".
I'm not saying that the other answers are wrong, they are all calling wrappers around the base method sometimes suppressing the stack in case of issues.
Have a look at my extension method
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);
}
}
}
There is no guarantee that the email will be sent, also errors are not populated back to the caller, however as a non-blocking method to send emails to all users of a given group... why not. having no error and no slow response sending an email to all users in a given group may just be fine for your use case.
I would then call the extension method as shown in the controller sample bellow.
No blocking and in my case, there is no stress if we miss an email as the logs contain the error that the user experience es well.... just who is really looking at logs ;-)
[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);
}
}