Petrus Theron
Petrus Theron

Reputation: 28807

SmtpClient.SendAsync Calls are Automatically Cancelled

Whenever I call smtpClient.SendAsync(...) from within my ASP.NET MVC application, the asynchronous requests are automatically cancelled, even though SendAsyncCancel() is never called.

Synchronous .Send(...) requests, on the other hand, go through just fine.

My EmailService service wrapper handles sending asynchronous email with SmtpClient from within my ASP.NET MVC 3 application. A service instance is injected into each MVC controller by StructureMap, which wraps a new SmtpClient instance in a using (...) { } statement.

Here is my EmailService.SendAsync wrapper method for SmtpClient:

public void SendAsync(EmailMessage message)
{
    try
    {
        using (var smtpClient = new SmtpClient(_cfg.Host, _cfg.Port)
        {
            EnableSsl = _cfg.EnableSsl,
            Credentials = _credentials
        })
        {
            smtpClient.SendCompleted += new SendCompletedEventHandler(Email_OnCompleted);

            var mailMessage = new MailMessage(message.From, message.To)
                                {
                                    Subject = message.Subject,
                                    Body = message.Body
                                };

            smtpClient.SendAsync(mailMessage, message);

            _logger.Info(string.Format("Sending async email to {0} with subject [{1}]", message.To, message.Subject));
        }
    }
    catch (Exception ex)
    {
        _logger.Error("Async email error: " + ex);
        throw;
    }

}

Here is my Email_OnCompleted delegate:

public void Email_OnCompleted(object sender, AsyncCompletedEventArgs e)
{
    var mail = (EmailMessage)e.UserState;

    if (e.Error != null)
    {
        _logger.Error(string.Format("Error sending email to {0} with subject [{1}]: {2}", mail.To, mail.Subject, e.Error));
    }
    else if (e.Cancelled)
    {
        _logger.Warn(string.Format("Cancelled email to {0} with subject [{1}].", mail.To, mail.Subject));
    }
    else
    {
        _logger.Info(string.Format("Sent email to {0} with subject [{1}].", mail.To, mail.Subject));
    }
}

Why are async emails being cancelled, but synchronous emails go through just fine? Could it be a dispose issue?

Upvotes: 12

Views: 5652

Answers (1)

Anders Abel
Anders Abel

Reputation: 69250

It can definitely be a dispose issue. When you dispose the client it cancels any outstanding async operations.

You should dispose the client in Email_OnCompleted.

An SO post on where to dispose: Dispose SmtpClient in SendComplete?

Upvotes: 19

Related Questions