2014-11-24 2 views
0

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 ---Я попытался отправить 300 писем по одному и тому же адресу электронной почты из моей программы. Я получаю ниже SMTP Exception

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) 
    { 

    } 
} 

Как я могу избежать этой ошибки?

+0

Как насчет отображения какого-то кода? Отсюда совершенно нечего уходить. Google сообщение об ошибке, если это все, что у вас есть. – techvice

+0

Можете ли вы опубликовать код объекта почтового клиента, особенно SendAsync? – DevEstacion

+0

Да, я добавил код. – user3332414

ответ

0

Используйте объект ManualResetEvent. Я предполагаю, что SmtpClient в настоящее время расположен, поэтому он теряет подписку на 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 
} 
0

Скорее всего, проблема в том, что тот же экземпляр MailMessage передается DispatchMail. MailMessage не является потокобезопасным по дизайну, и каждый SmtpClient.SendAsync внутренне вызывает Message.BeginSend.

Итак, когда несколько потоков пытаются отправить то же самое MailMessage, при вызове есть условие гонки. Если EndSend вызывается той же веткой, которая называется BeginSend - нам повезло. Если нет - исключение из выше поднимается,

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

Решение здесь либо скопировать MailMessage для каждого вызова SendAsync, или использовать SendAsync перегрузку, которая принимает 5 параметров:

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

Edit: Это исключение очень легко воспроизвести, чтобы доказать, что MailMessage не является потокобезопасным. Вы можете получить несколько исключений, IAsyncResult один из выше, или Item has already been added при наполнении заголовков:

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(); 
    } 
}