0
votes

Error: System.Net.Mail.SmtpException: Failure sending mail. ---> System.ArgumentException: The IAsyncResult object was not returned from the corresponding asynchronous method on this class. Parameter name: asyncResult at System.Net.Mime.MimeBasePart.EndSend(IAsyncResult asyncResult) at System.Net.Mail.Message.EndSend(IAsyncResult asyncResult) at System.Net.Mail.SmtpClient.SendMessageCallback(IAsyncResult result) --- End of inner exception stack trace ---

private void DispatchMail(MailMessage message, MessageTrackerObject trackInfo)
{
    SmtpClient mailClient = new SmtpClient();
    mailClient.Host = ConfigurationManager.AppSettings[(Constants.FAXSETTINGS_SMTPSERVER)];
    mailClient.Port = int.Parse(ConfigurationManager.AppSettings[(Constants.FAXSETTINGS_SMTPPORT)]);
    //mailClient.DeliveryMethod = SmtpDeliveryMethod.Network;


    NetworkCredential ntCredential = new NetworkCredential();

    if (GetStaticSetting(Constants.APPCONFIG_KEY_MAILWINDOWSAUTH).ToLower() == "true")
    {
        //mailClient.UseDefaultCredentials = true;
    }
    else
    {
        ntCredential.UserName = GetStaticSetting(Constants.APPCONFIG_KEY_MAILUSERID);
        ntCredential.Password = GetStaticSetting(Constants.APPCONFIG_KEY_MAILPASSWORD);
        mailClient.Credentials = ntCredential;
        mailClient.UseDefaultCredentials = false;
    }

    mailClient.EnableSsl = GetStaticSetting(Constants.APPCONFIG_KEY_MAIL_SSL).ToLower() == "true";
    mailClient.SendCompleted += new SendCompletedEventHandler(MailClient_SendCompleted);
    mailClient.SendAsync(message, trackInfo);
    //mailClient.Send(message);
}

private void MailClient_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
    string error = "";
    MessageTrackerObject data = (MessageTrackerObject)e.UserState;

    string msg = string.Format("File: {0}", data.Info);
    try
    {
        foreach (string serial in data.Serials)
        {
            if (e.Cancelled)
            {
                error = e.Error != null ? String.Format(" #Error: {0}", e.Error.ToString()) : "";
                string cancelled = string.Format("{0} Send canceled. {1}", msg, error);
                SetFaxStatus(serial, FaxStatus.Cancelled, cancelled);
            }
            else if (e.Error != null)
            {
                error = String.Format("{0} #Error: {1}", msg, e.Error.ToString());
                SetFaxStatus(serial, FaxStatus.Error, error);
            }
            else
            {
                SetFaxStatus(serial, FaxStatus.Sent, string.Format("{0} Mail sent successfully.", msg));
            }
        }
        //release resource
        data.Message.Dispose();
    }
    catch (Exception ex)
    {

    }
}

How can i avoid this error?

2
How about displaying some code? There is absolutely nothing to go off of here. Google the error message if that is all you have.techvice
Can you post the mail client object code, specially the SendAsync?DevEstacion
Yes i have added the code.user3332414
@user3332414 I've added an answerDevEstacion

2 Answers

1
votes

Most probably the problem here is that the same instance of MailMessage is passed to DispatchMail. MailMessage is not thread-safe by design, and each SmtpClient.SendAsync is internally invoking Message.BeginSend.

So, when several threads are attempting to send same MailMessage, there is a race condition when calling Message.EndSend. If EndSend is invoked by the same thread which called BeginSend - we are in luck. If not - exception from above is raised,

The IAsyncResult object was not returned from the corresponding asynchronous method on this class

Solution here is either to copy MailMessage for each call of SendAsync, or use SendAsync overload which accepts 5 parameters:

void SendAsync(string from, string recipients, string subject, string body, object token)

Edit: This exception is very easy to reproduce, to prove that MailMessage is not thread-safe. You may get several exceptions, IAsyncResult one from above, or Item has already been added when populating headers:

using System;
using System.Net.Mail;
using System.Threading.Tasks;
class App
{
  static void Main()
  {
     var mail = new MailMessage("[email protected]", "[email protected]", "Test Subj", "Test Body");
     var client1 = new SmtpClient("localhost");
     var client2 = new SmtpClient("localhost");
     var task1 = client1.SendMailAsync(mail);
     var task2 = client2.SendMailAsync(mail);
     Task.WhenAll(task1, task2).Wait();
  }
}
0
votes

Use the ManualResetEvent object. I'm guessing the SmtpClient is being disposed that's why it's losing the subscription to MailClient_SendCompleted

ManualResetEvent resetEvent;
private void DispatchMail(MailMessage message, MessageTrackerObject trackInfo)
{
    // other code here
    resetEvent = new ManualResetEvent(false);
    mailClient.EnableSsl = GetStaticSetting(Constants.APPCONFIG_KEY_MAIL_SSL).ToLower() == "true";
    mailClient.SendCompleted += new SendCompletedEventHandler(MailClient_SendCompleted);
    mailClient.SendAsync(message, trackInfo);
    resetEvent.WaitOne(TimeSpan.FromSeconds(5)); // waits for 5 seconds
    //mailClient.Send(message);
}

private void MailClient_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
    resetEvent.Set(); // removes the wait after successfully sending
    string error = "";
    MessageTrackerObject data = (MessageTrackerObject)e.UserState;
    // other code here
}