1

When i program with C# to send a mail by batch,my code is like this:

public static bool Send(MailAddress Messagefrom,
    string MessageTo,
    string MessageSubject,
    string MessageBody)
{
    MailMessage message = new MailMessage();
    message.From = Messagefrom;
    message.To.Add(MessageTo);
    message.Subject = MessageSubject;
    message.Body = MessageBody;            
    message.BodyEncoding = System.Text.Encoding.UTF8;
    //message.SubjectEncoding = Encoding.BigEndianUnicode;
    message.IsBodyHtml = true;
    message.Priority = MailPriority.High;            
    MailHelper mh = new MailHelper();
    SmtpClient sc = mh.setSmtpClient("smtp.qq.com", 25);   
    sc.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);  
    try
    {                
        sc.SendAsync(message, message);                
    }
    catch (Exception e)
    {
        LogHelper.WriteLog("Main send failed....\t the detail info:" + 
            e.ToString());
        return false;
    }
    return true;
}

This is a problem!When the first mail send failed(for example the mail address is null),the next mail can't be send!

Because i have so much mail wait to send,if this situation,how to fix it?For example the failed mail may still on this table and Administator to deal it by hand.

But this situation probably in Send function,Why this happen?

Jonathan Nixon
  • 4,940
  • 5
  • 39
  • 53
Dolphin
  • 29,069
  • 61
  • 260
  • 539
  • 2
    Are you sending the mails in a foreach loop? You should change the caller of Send() so that when it crashes for one mail, log the error and continue sending the next message – RononDex Dec 04 '13 at 13:38
  • Yes,i using a foreach loop,still using the loop? – Dolphin Dec 04 '13 at 13:45
  • You could try calling the SendAsyncCancel method in the catch block. See http://msdn.microsoft.com/library/x5x13z6h.aspx under "Remarks". – Frank Dec 04 '13 at 13:46
  • the SendAsync() function don't send the next message when crashes?If that why called async? – Dolphin Dec 04 '13 at 13:47
  • From the microsoft knowlede base: After calling SendAsync, you must wait for the e-mail transmission to complete before attempting to send another e-mail message using Send or SendAsync. - So I guess that you would have to cancel the send process. – Frank Dec 04 '13 at 13:53
  • Can implemention not wait?Or the wait time<5S or less?Beacause the mail is 30 per second – Dolphin Dec 04 '13 at 13:55
  • SendAsync is a non-blocking method. Your program doesn't wait for the method to finish the send process. So it will not block the current thread. But you can not send another mail at the same time. – Frank Dec 04 '13 at 14:00
  • Then use Send() and not SendAsync. All Async function start a new thread that executes the function. So your code will not wait until it is executed. If you really can only send 1 mail per time then using the Async function makes no sense in your case. Just use Send() instead of SendAsync() – RononDex Dec 04 '13 at 14:16

1 Answers1

2

You have to catch errors in the foreach loop that calls your Send() function and log the errors somewhere:

foreach (var mail in mailsToSend)
{
    try
    {
        // Call your send function
        Send(...)
    }
    catch (Exception ex)
    {
        // Log the error somewhere (console, file, ...)
        Console.WriteLine("Error sending mail {0}", mail);
    }
}

This ensures that the application won't crash when one email fails to send and continue sending the other mails.

Also you should use Send() instead of SendAsync() in your Send() function. This is because the SendAsync function starts a new thread for sending the mail, while Send will stop your programs execution until the mail has been sent. One more reason you shouldn't use the SendAsync function is because according to microsoft only 1 mail can be send at a time. That means using the SendAsync function for more then 1 mail will cause it to throw an exception.

RononDex
  • 4,143
  • 22
  • 39