从webApi发送两封电子邮件异步

时间:2014-03-10 13:43:07

标签: c# asp.net-web-api

我有一个webApi设置(WebApi2)。 post方法的一个要求是(取决于一些变量)发送2封电子邮件。

我不希望客户端等待发送电子邮件。我希望他们只是提出请求并继续前进。

所以我认为我应该使用smtpClient.SendAsync,但我一直在客户端上获得http 500内部错误 - 一个c#winforms app

当我使用普通的smtpClient.Send时工作正常。但不是SendAsync。 我似乎无法抓住服务器上的错误来找到问题 - 驱使我有点稀,并且错误没有帮助。我只能假设它是由于错误地发送电子邮件

示例代码如下

//Web api code
private MessageDto _messageDto = null;
public void PostAddinObject(AddinObject newObject)
{
    _messageDto = new MessageDto();
    _messageDto.Email = "bob@moo.com";
    ..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代码:

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

2 个答案:

答案 0 :(得分:3)

您可以使用Task.WhenAllawait个多项任务。这将确保第一封电子邮件不会阻止第二封电子邮件。在下面的示例中,请求大约需要3秒钟才能完成(请注意Task.Delay方法中的SendEmail)。

public async Task Post()
{
    await Task.WhenAll(
        SendEmail("a@b.com"),
        SendEmail("b@c.com")
    );
}

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

        await client.SendMailAsync(
            new MailMessage("test@test.com", to, "Test", "Test"));
    }
}

你说:

  

我希望他们只是提出请求并继续前进。

严格地说,上面的内容仍然让客户等待回复,这比你以前做的更有效。

如果您想“发射并忘记”,那么推荐的方法是将电子邮件添加到队列/数据库,并使用后台进程/服务来实际发送电子邮件。

也就是说, 可能只是在后台线程上启动工作,但是你应该谨慎行事并确保添加适当的异常处理:

public void Post()
{
    Task.Factory.StartNew(() =>
    {
        SendEmail("a@b.com");
        SendEmail("b@c.com");
    });
}

这将立即返回,而不是等待发送电子邮件。这也意味着你无法真正给你的客户任何成功的迹象。

答案 1 :(得分:0)

来自documentation

  

调用SendAsync后,您必须等待电子邮件传输到   在尝试使用“发送”发送另一封电子邮件之前完成   或SendAsync。

此外,我确保在发送电子邮件之前不会销毁SmtpClient对象。您的代码不提供该保证。