1

I am trying to send E-mails asynchronously and it works fine as long as there isn't an AlternateView attached to the e-mail. When there is an alternate view, I get the following error:

Cannot access a disposed object. Object name: 'System.Net.Mail.AlternateView'
System.Net.Mail.SmtpException: Failure sending mail. ---> System.ObjectDisposedException: Cannot access a disposed object.

Object name: 'System.Net.Mail.AlternateView'.
   at System.Net.Mail.AlternateView.get_LinkedResources()
   at System.Net.Mail.MailMessage.SetContent()
   at System.Net.Mail.MailMessage.BeginSend(BaseWriter writer, Boolean sendEnvelope, AsyncCallback callback, Object state)
   at System.Net.Mail.SmtpClient.SendMailCallback(IAsyncResult result)

Here is some sample code:

Dim msg As New System.Net.Mail.MailMessage
msg.From = New System.Net.Mail.MailAddress("me@example.com", "My Name")
msg.Subject = "email subject goes here"

'add the message bodies to the mail message
Dim hAV As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(textBody.ToString, Nothing, "text/plain")
hAV.TransferEncoding = Net.Mime.TransferEncoding.QuotedPrintable
msg.AlternateViews.Add(hAV)

Dim tAV As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(htmlBody.ToString, Nothing, "text/html")
tAV.TransferEncoding = Net.Mime.TransferEncoding.QuotedPrintable
msg.AlternateViews.Add(tAV)

Dim userState As Object = msg
Dim smtp As New System.Net.Mail.SmtpClient("emailServer")

'wire up the event for when the Async send is completed
 AddHandler smtp.SendCompleted, AddressOf SmtpClient_OnCompleted

 Try
     smtp.SendAsync(msg, userState)
 Catch '.... perform exception handling, etc...
 End Try

And the Callback.....

 Public Sub SmtpClient_OnCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
    If e.Cancelled Then
      'Log the cancelled error
    End If
    If Not IsNothing(e.Error) Then
        'Log a real error....
        ' this is where the error is getting picked up
    End If

    'dispose the message
    Dim msg As System.Net.Mail.MailMessage = DirectCast(e.UserState, System.Net.Mail.MailMessage)
    msg.Dispose()

End Sub
hacker
  • 1,115
  • 1
  • 15
  • 28

3 Answers3

2

The reason this isn't working is because your OnCompleted handler is being called when the SendAsync() method completes, but that appears to be before the SmtpClient has finished physically sending the email across the network (this will only happen with network delivery though, file deliveries are essentially synchronous with SendAsync()).

This almost seems like a bug in the SmtpClient because OnCompleted should really only be called when the message has truly been sent.

Jeremy Wiebe
  • 3,894
  • 22
  • 31
  • I've sent a submission off to Microsoft. We'll see if that gets me anywhere. – hacker Apr 24 '09 at 17:15
  • Microsoft replied and indicated that they were able to get it to work fine without an error. I haven't had a chance to get back to that application in order to re-apply sending e-mail Asynchronously and test it. – hacker May 05 '09 at 12:53
0

You should put your dims at the class level if you want to access them in your callback.

private msg As System.Net.Mail.MailMessage
private hAV As System.Net.Mail.AlternateView 

private sub yoursub
  msg = new System.Net.Mail.MailMessage(..
  hAV = new ...
end sub

My guess is that AlternateViews.Add merely adds a reference of hAV, the msg object needs dispose while the hAV is disposed automatically by the GC..

Cheers

Evolved
  • 599
  • 6
  • 5
0

I had a very similiar issue. Same error message, but a slightly different code structure. In my case I was disposing of the mailmessage object inside the main function. By the time the OnCompleted event ran, the object was already gone.

Look at your code after the SendAsync to see if you are freeing the mailmessage object. For example, if you are creating it inside a using statement, then it will be freed before the async event is run.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • I did check that because initially, I did have the MailMessage being disposed in the finally block. Unfortunately, the AlternateViews aren't being disposed (at all now) and the MailMessage is disposed of at the end of the OnCompleted block. The error occurs before it even gets to the MailMessage dispose call. One thing that I am thinking of is that the GC is collecting the object too quick... not sure if that's possible though. – hacker Apr 25 '09 at 13:15