1

Application requires that a use SendAsync rather than just Send. So i Made a Class CEmailServer and set up everything. So far Send works fine but when changing it to work with SendAsync it does not. I Created a Method to be called when a mail is sent and the userToken is in place but it keeps failing. i Can't find my error. Here is my code :

static bool mailSent = false;

//Method for Sending with attachment.
public void SendEmail(string Address, string Recipient, string Subject, string Body, string Dir)
{
    var fromAddress = new MailAddress("someadress.kimberley@gmail.com", "My Company");
    var toAddress = new MailAddress(Address, Recipient);
    const string fromPassword = "password";
    string subject = Subject;
    string body = Body;

    var smtp = new SmtpClient
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        DeliveryMethod = SmtpDeliveryMethod.Network,
        UseDefaultCredentials = false,
        Credentials = new NetworkCredential(fromAddress.Address, fromPassword)

    };
    using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    })
    {
        smtp.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
        string userState = "Test";
        message.Attachments.Add(new Attachment(Dir));
        smtp.SendAsync(message,userState);
        message.Dispose();
    }
}

//Method for Sending regular message without attachment.
public void SendEmail(string Address, string Recipient, string Subject, string Body)
{
    var fromAddress = new MailAddress("someadress.kimberley@gmail.com", "My Company");
    var toAddress = new MailAddress(Address, Recipient);
    const string fromPassword = "password";
    string subject = Subject;
    string body = Body;

    var smtp = new SmtpClient
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        DeliveryMethod = SmtpDeliveryMethod.Network,
        UseDefaultCredentials = false,
        Credentials = new NetworkCredential(fromAddress.Address, fromPassword)

    };
    using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    })
    {
        smtp.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
        string userState = "Message Sent";
        smtp.SendAsync(message, userState);
        message.Dispose();
    }
}

//Method to be called when sending is complete
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
    // Get the unique identifier for this asynchronous operation.
    String token = (string)e.UserState;

    if (e.Cancelled)
    {
        MessageBox.Show("Sending Canc");
    }
    if (e.Error != null)
    {
        MessageBox.Show("Error Sending Mail");
    }
    else
    {
        MessageBox.Show("Message sent.");
    }
    mailSent = true;
}

Thank you very much!

Mordacai1000
  • 329
  • 1
  • 3
  • 14

1 Answers1

6

You are disposing the message before the send can complete. You should be disposing them in the SendCompleted callback event. Here's an example of the best way to dispose the client and the message.

Your code should look something like this:

var smtp = new SmtpClient
{
    Host = "smtp.gmail.com",
    Port = 587,
    EnableSsl = true,
    DeliveryMethod = SmtpDeliveryMethod.Network,
    UseDefaultCredentials = false,
    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};

var message = new MailMessage(fromAddress, toAddress)
{
    Subject = subject,
    Body = body,
};

smtp.SendCompleted += (s, e) => {
    SendCompletedCallback(s, e);
    smtp.Dispose();
    message.Dispose();
};
string userState = "Test";
message.Attachments.Add(new Attachment(Dir));
smtp.SendAsync(message, userState);
Community
  • 1
  • 1
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • 1
    @Mordacai1000 Did you take the `message` out of the `using` statement as well? Also, it would be helpful if you could provide the details of the exception. – Mike Zboray Jan 18 '14 at 20:38
  • I did not remove message. Here is the error : System.Net.Mail.SmtpException: Failure sending mail. ---> System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Mail.MailMessage'. at System.Net.Mail.MailMessage.get_AlternateViews() at System.Net.Mail.MailMessage.SetContent(Boolean allowUnicode) at System.Net.Mail.SmtpClient.SendMailCallback(IAsyncResult result) --- End of inner exception stack trace --- – Mordacai1000 Jan 18 '14 at 20:55
  • Thank you very much, wil test it in the morning – Mordacai1000 Jan 18 '14 at 22:24
  • Can anyone here also tell me that whose **dispose()** method should be called first in **SendCompleted** event handler i.e **msg.dispose()** OR **smtpclient.dispose()** ? – vibs2006 Jan 08 '17 at 16:00