Crudler
Crudler

Reputation: 2286

sending two emails async from webApi

i have a webApi setup (WebApi2). One of the requirements of the post method is (depending on some variables) send 2 emails.

I don't want the client to have to wait for the emails to be sent. I want them to just make the request and move on.

So I supposed that I should be using smtpClient.SendAsync but I keep getting http 500 internal error on the client - a c# winforms app

Works fine when I use normal smtpClient.Send. but not SendAsync. And I can't seem to catch the error on the server to locate the problem - drives me a bit dilly, and the error doesn't help. I can only assume its due to sending the email through incorrectly

Sample code as follows

//Web api code
private MessageDto _messageDto = null;
public void PostAddinObject(AddinObject newObject)
{
    _messageDto = new MessageDto();
    _messageDto.Email = "[email protected]";
    ..do dome otherstuff
    SendMail("Hello Dot");
    SendMail("Hello Peg");
    ..finish up and leave
 }



private void SendMail(String msg)
{
    using (var message = new MailMessage())
    {
        message.To.Add(_messageDto.Email);
        message.Subject = "Hello;
        message.Body = msg

        try
        {
             Attachment datAttachment = new Attachment(_pdfFilePath, MediaTypeNames.Application.Pdf);  //gets the pdf file from somewhere special
             ContentDisposition disposition = datAttachment.ContentDisposition;
             disposition.CreationDate = File.GetCreationTime(_pdfFilePath);
             disposition.ModificationDate = File.GetLastWriteTime(_pdfFilePath);
             disposition.ReadDate = File.GetLastAccessTime(_pdfFilePath);

             message.Attachments.Add(datAttachment);
         }
         catch (Exception exception)
         {                   
              throw;
         }

         var smtpClient = new SmtpClient();
         smtpClient.SendCompleted += new SendCompletedEventHandler(OnSendCompletedCallback);
         smtpClient.SendAsync(message, null); 
    }
}

winforms code:

HttpClient _client=new HttpClient(); 
var response = _client.PostAsJsonAsync("api/Addin", newObject).Result;

Upvotes: 0

Views: 2646

Answers (2)

Ben Foster
Ben Foster

Reputation: 34800

You can use Task.WhenAll to await multiple tasks. The will ensure the first email will not block the second. In the example below the request takes approx 3 seconds to complete (note the Task.Delay in the SendEmail method).

public async Task Post()
{
    await Task.WhenAll(
        SendEmail("[email protected]"),
        SendEmail("[email protected]")
    );
}

private async Task SendEmail(string to)
{
    using (var client = new SmtpClient())
    {
        await Task.Delay(3000);

        await client.SendMailAsync(
            new MailMessage("[email protected]", to, "Test", "Test"));
    }
}

You stated:

I want them to just make the request and move on.

Strictly speaking the above still makes the client wait for a response, it's just more efficient that what you were doing before.

If you want to "fire and forget" then the recommended approach is to add the emails to a queue/database and use a background process/service to actually send the emails.

That said, it is possible to just fire off the work on a background thread but you should tread carefully here and make sure you add proper exception handling:

public void Post()
{
    Task.Factory.StartNew(() =>
    {
        SendEmail("[email protected]");
        SendEmail("[email protected]");
    });
}

This will return immediately rather than waiting for the emails to be sent. This also means you can't really give your client any indication of success.

Upvotes: 3

Marius Bancila
Marius Bancila

Reputation: 16328

From the documentation:

After calling SendAsync, you must wait for the e-mail transmission to complete before attempting to send another e-mail message using Send or SendAsync.

Also, I'd make sure the SmtpClient object does not get destroyed before the e-mail has been sent. Your code does not provide that guarantee.

Upvotes: 0

Related Questions