0

I just want to have a function, which will be sending mail to different people.

I have written a Email Service, just like this:

 public void SendEMail(EMail mail)
    {
        var body = JObject.FromObject(settings);
        body.Merge(JObject.FromObject(mail));

        GlobalTelemetry.TrackDependency("E-Mail Service", "Send", () =>
        {
            var result = AsyncHelper.RunSync(() => httpClient.PostAsync(azureFunctionUrl,
                new StringContent(body.ToString(), Encoding.UTF8, "application/json")));
            if (!result.IsSuccessStatusCode)
            {
                throw new InvalidOperationException(
                    $"E-Mail Service failed to send mails. Http Status {result.StatusCode}. Please check if the Url '{azureFunctionUrl}' is correct. Env: {Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}");
            }
        });
    }

and by every other functions, which want to use this mail service, do just like this:

 SendMail = mail =>
        {
            var fireAndForgetTask = Task.Run(() =>
            {
                try
                {
                    eMailService.SendEMail(mail);
                }
                catch (Exception e)
                {
                    Log.Fatal(e, $"Fail to send  E-Mail to: '{mail.To}'");
                }
            });
        };

it does work, but fireAndForgetTask is not used, I have no idea how to do it better. Is it necessary to write a Email Job???

Some better suggestion is welcome :-)

user1938143
  • 1,022
  • 2
  • 22
  • 46

1 Answers1

0

I had a similar issue in my app for sending a password reset email, I did not want the delay of waiting for the email to send because if a hacker is trying to find out if an account exists for an email address the delay could indicate that the account does exist. So I wanted to fire and forget the email with no delay.

So I implemented a simple extension method named forget like this in a separate static class based on this so question:

public static void Forget(this Task task)
{

}

and then I send my email async and use that .Forget extension to not wait for it like this:

emailSender.SendPasswordResetEmailAsync(
Site,
model.Email,
sr["Reset Password"],
resetUrl).Forget();

note that I am not using "await" when I call this async method and the .Forget gets rid of the warning that would otherwise appear in Visual Studio when calling an async method without the await keyword

Joe Audette
  • 35,330
  • 11
  • 106
  • 99