Question

I was using SMTPClient.Send(mail) method to send emails, but then I saw, if the email id is not present (does not exists), my application waits till it receives the exception and then allows user to perform further tasks.

So I thought of using SMTPClient.SendAsync Method.

My doubt!! Where can this userToken Object be used which is passed as the parameter to the method? I searched many things online but din't find a good example. Even in MSDN they use it like this

string userState = "test message1";
client.SendAsync(message, userState);

But then what can it be really used for?

Thank you in advance.

Was it helpful?

Solution

You may use it in the following case: imagine that you have application for batch email sending. You compose message(different messages\attachments for every recipient, so you can't combine it into a single message), select for example 20 recipients and press button "Send All". For sending you use SendAsync and several SmtpClient instances from the "pool"(as SmtpClient doesn't allow to call SendAsync twice on one instance before previous call isn't completed).

You have a single SmtpClientSendCompleted handler for all SendAsync calls in which you should perform advanced logging: log result of the sending, names (addresses or even attachments) of the recipients of failed messages, but AsyncCompletedEventArgs can provide this information only with help of UserState. So the basic pattern for this purpose is to use custom user state object. So see the simplified example:

Interface which contains fields you will need in the handler:

public interface IEmailMessageInfo{
   string RecipientName {get;set;}
}

Async state class:

/// <summary>
/// User defined async state for SendEmailAsync method
/// </summary>
public class SendAsyncState {

    /// <summary>
    /// Contains all info that you need while handling message result
    /// </summary>
    public IEmailMessageInfo EmailMessageInfo { get; private set; }


    public SendAsyncState(IEmailMessageInfo emailMessageInfo) {
        EmailMessageInfo = emailMessageInfo;
    }
}

Here the code for sending email:

SmtpClient smtpClient = GetSmtpClient(smtpServerAddress);
smtpClient.SendCompleted += SmtpClientSendCompleted;
smtpClient.SendAsync(
   GetMailMessage()
   new SendAsyncState(new EmailMessageInfo{RecipientName = "Blah-blah"})
);

And the handler code example:

private void SmtpClientSendCompleted(object sender, AsyncCompletedEventArgs e){
    var smtpClient = (SmtpClient) sender;
    var userAsyncState = (SendAsyncState) e.UserState;
    smtpClient.SendCompleted -= SmtpClientSendCompleted;

    if(e.Error != null) {
       tracer.ErrorEx(
          e.Error, 
          string.Format("Message sending for \"{0}\" failed.",userAsyncState.EmailMessageInfo.RecipientName)
       );
    }

    // Cleaning up resources
    .....
}

Please, let me know if you need more details.

OTHER TIPS

If you are using async(), you need to also have the event handler.

   static void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        //to be implemented        
    }

This is fine to send email using Async() method. Hope this is helpful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top