none
System.Net.Mail.SmtpClient.SendAsync fails in 4.5 RRS feed

  • Question

  • In previous versions I had this working by using the SendCompleted event:

    smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);

    But now in 4.5 I get a System.Net.Mail.SmtpExcpetion with an inner exception:

    "An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle."

    Does this suggest the SendCompleted event is no longer used and you have to go through the whole await/async process?  That would mean adding async/await/Task code everywhere up the call stack from the web controller method which would be a huge pain.

    Anyone else see this?

    Thursday, June 28, 2012 12:45 PM

Answers

  • Sorry but that doesn't make sense.  If you close the connection before sending then it won't get sent?

    Anyway I've come to the conclusion that SmtpClient.SendAsync and the async/await/Task mechanism don't play together well so I've now just got an awaitable wrapper function around SmtpClient.Send() along these lines, which seems to work:


    public static async Task<bool> SendEmailAwaitable(MailMessage message, string server, int port) {	
     SmtpClient smtpClient = new SmtpClient(server, port);
     smtpClient.Send(messsage);	
     await Task.Yield();	
     return true;
    }

    I was getting this exception when trying to call SmtpClient.SendAsync() within the above block of code, which makes sense:

    "An asynchronous module or handler completed while an asynchronous operation was still pending"

    Monday, July 16, 2012 7:01 AM

All replies

  • Where the code actually is executed? The second sentence success that you are using asyncronous operation at the wrong place in ASP.NET page?
    Thursday, June 28, 2012 4:46 PM
  • Hi Deejbee,

    Welcome to the MSDN Forum.

    As MasaSam said, where do you call the SendAsync method?

    As you know, 4.5 has changed about asynchronous  method: http://msdn.microsoft.com/en-us/library/ms171868(v=vs.110).aspx 

    In the .NET Framework 4.5 RC, new asynchronous features were added to the C# and Visual Basic languages. These features add a task-based model for performing asynchronous operations.

    I hope this will be helpful.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Tuesday, July 3, 2012 12:17 PM
    Moderator
  • Hi,

    Not sure if your problem is the same as mine, but I get the same error message when sending an email using a third-party email helper (ActionMailer) from a normal action method in a plain Asp.Net MVC 4 Controller. I don't know of a good fix, but in my case a temporary workaround has been to "comment out" in web.config an app setting suggested after I upgraded to .Net 4.5.

    The app setting I removed from web.config is

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 

    (or set its value to false).

    Hope this might help,

    --philip

    • Marked as answer by Mike FengModerator Sunday, July 8, 2012 10:13 AM
    • Unmarked as answer by deejbee1 Thursday, July 12, 2012 10:43 AM
    • Proposed as answer by lukencode Monday, February 25, 2013 10:38 PM
    • Unproposed as answer by lukencode Monday, February 25, 2013 10:39 PM
    Saturday, July 7, 2012 6:10 PM
  • Thanks Philip, that worked, although I'm not all that comfortable with it.

    The new async/await Task<> pipeline in 4.5 is great for stream and web since they seem to be supported but I don't see the same for sending email, which I would have thought would have been an ideal candidate for async/await.  

    From what I can tell, the above web.config switch provides protection to programmers who accidentally write code that they think is async, but isn't, hence why I'm a bit reluctant to use a heavy duty switch like that.

    Is there a 4.5 method for sending email async without using the switch you described?

    Wednesday, July 11, 2012 5:42 PM
  • As I expected that above switch has undesired consequences.  It causes awaited tasks to continue immediately and so any code after it fails because the value returned from the awaiting task is null.  Switching the flag back to true returns to the expected functionality but obviously the original problem with SendAsync() returns.

    So it seems you can only do this stuff either one way or the other but not mix the two?  I'd really like to hear from anyone who knows how to send async email the right way (using async/await)...

    Thursday, July 12, 2012 10:42 AM
  • TGhe send complete event is defined as follows:

    The SendCompleted event is raised each time an e-mail message is sent asynchronously when the send operation completes. To send an e-mail message asynchronously, use the SendAsync methods.

    So if you are sending a large email use async method in chunks of 1500 bytes you will get an event flag raised when the 1500 byres are sent so you can fill the async send buffer with more data.  You cannot use the Sendcomplete event when sending data synchronously.  You also must close the connection before the email is actually sent by the server because the server won't know when the end of the message occurs until the connection is closed.


    jdweng

    Thursday, July 12, 2012 11:47 AM
  • Sorry but that doesn't make sense.  If you close the connection before sending then it won't get sent?

    Anyway I've come to the conclusion that SmtpClient.SendAsync and the async/await/Task mechanism don't play together well so I've now just got an awaitable wrapper function around SmtpClient.Send() along these lines, which seems to work:


    public static async Task<bool> SendEmailAwaitable(MailMessage message, string server, int port) {	
     SmtpClient smtpClient = new SmtpClient(server, port);
     smtpClient.Send(messsage);	
     await Task.Yield();	
     return true;
    }

    I was getting this exception when trying to call SmtpClient.SendAsync() within the above block of code, which makes sense:

    "An asynchronous module or handler completed while an asynchronous operation was still pending"

    Monday, July 16, 2012 7:01 AM
  • Thanks for this code deejbee1. Worked like a charm.

    Wednesday, August 28, 2013 4:51 PM
  • But did you see the SmtpClient.SendMailAsync method? You can await on it, which is a wrapper around the SendAsync method.


    Martín Coll - mi blog es martincoll.com.ar, date una vuelta!

    Friday, September 12, 2014 1:42 PM