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("[email protected]", "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
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.