SMTP Email send on new thread

Hello,

I'm working on a winform application that sends and reads emails regularly.  I use the following code in a module to send email and I'd like it to run in the background so the UI stays active.  I tried using async email sending but that failed after awhile on certain machines.  I have no idea why it would work for a few hours then fail to send.  I'm switching over to a sync send but creating a new thread to send it.  The part I'm having trouble with is updating an richtextbox (rtLog) on MainForm from the module along with a label, also on the MainForm.  I know it has something to do with invoking, etc. but I haven't been able to figure out how to do so with this simple multithreading problem.  

From the error I get on the lines:

MainForm.lblStatus.text = "Sending Mail"
MainForm.rtLog.AppendText(Now() & " " & Info & vbCrLf)

I'd think I'm erroneously trying to create a new form from the thread.  I want to just update the original calling thread/form's rtLog and lblStatus.  If I knew what I was doing it would be a typical cross thread operation?

Here's the error I get:


An error occurred creating the form. See Exception.InnerException for details.  The error is: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.

Any thoughts would be appreciated!

Heres the code:

Module Module1

    Dim mail As New MailMessage()
    Dim SmtpServer As New SmtpClient()


   Public Sub SendMail(ByVal strFrom As String, ByVal strTo As String, _
    ByVal strCC As String, ByVal strSubject As String, ByVal strBody As String, ByVal strAttachments As String, ByVal strSMTPServer As String, _
    ByVal strMailLogin As String, ByVal strMailPassword As String, IsHTML As Boolean)

        Try
            
            SmtpServer = New SmtpClient()     
            SmtpServer.Credentials = New Net.NetworkCredential(strMailLogin, strMailPassword)
            SmtpServer.Port = 587
            SmtpServer.EnableSsl = True
            SmtpServer.Host = strSMTPServer
            mail = New MailMessage()
            mail.From = New MailAddress(strMailLogin)
            If strAttachments = "YES" Then
                Dim attachment As System.Net.Mail.Attachment
                Using attachment
                    attachment = New System.Net.Mail.Attachment(Application.StartupPath & "\")
                    mail.Attachments.Add(attachment)

                    attachment = New System.Net.Mail.Attachment(Application.StartupPath & "\")
                    mail.Attachments.Add(attachment)
                    attachment = New System.Net.Mail.Attachment(Application.StartupPath & "\")
                    mail.Attachments.Add(attachment)
                    attachment = New System.Net.Mail.Attachment(Application.StartupPath & "\")
                    mail.Attachments.Add(attachment)
                 
                End Using
            End If
            mail.To.Add(strTo)
            mail.Subject = strSubject
            mail.Body = strBody
            If IsHTML Then mail.IsBodyHtml = True
            
            Dim TS As New Thread(AddressOf SendMailNewThread)
            TS.IsBackground = True
	    TS.Name = "EmailSendThread"
            TS.Start()


        Catch ex As Exception
            SmtpServer.Dispose()
            mail.Dispose()
            LogIt("ERROR Sending email!" & ex.StackTrace)
        End Try

    End Sub


    Private Sub SendMailNewThread()

        Try

            LogIt("**** ATTEMPTING TO  SEND  MAIL  *****")
	    MainForm.lblStatus.text = "Sending Mail"		
            SmtpServer.Send(mail)
            mail.Dispose()
            SmtpServer.Dispose()
            MainForm.lblStatus.text = "Mail Sent"
            LogIt("**** COMPLETED SEND  MAIL  *****")
        Catch ex As Exception
            LogIt("ERROR Sending email!" & ex.StackTrace)
        End Try
    End Sub

    Public Sub LogIt(Info As String)

        Try
            MainForm.rtLog.AppendText(Now() & " " & Info & vbCrLf)
            Using outfile As StreamWriter = File.AppendText(Application.StartupPath & "\Log.txt")
                outfile.Write(Now() & " " & Info & vbCrLf)
                outfile.Close()
            End Using
        Catch ex As Exception

        End Try
    End Sub

End Module

Open in new window

zipnoticAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

UnifiedISCommented:
I don't understand what this means:   "I'd like it to run in the background so the UI stays active".  What triggers the sending of emails, the user clicking a button?
Seems like it would be simpler to update the status independent of the mail sending

click button
update status
call send mail function (return a boolean for success/failure)
update status based on result
zipnoticAuthor Commented:
It runs automatically for the most part without use interaction.  Bit if user happens to be sitting there and wants to peruse the datagridviews or other functionality then I want to allow that or not interupt that while emailing in background.  The email checks are on a timer.

Thanks for the thought!
CodeCruiserCommented:
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

zipnoticAuthor Commented:
CodeCruiser,

I tried to go down the backgroundworker route but I was having a little trouble with managing it within a module.  I don't have the code any more but the errors were crossthreading and data changed somewhere else type errors.  

Here's my basic framework:

The Main Form has a timer that checks an email account for new reports.  If one is found it immediately sends it out to several email addresses via SMTP with that same account.   On the user interface thread I check via IMAP and send via SMTP and I don't bother logging out of IMAP I just send it SMTP and it works.  This of course freezes the UI for the time sending or receiving email.  I tried async email send but it only worked some of the time giving a generic inner exception.  I put the send routine in a module and send byVal everything needed for the mail send.  Perhaps I should put the send mail routine back into the main form to make using BGW easier?  Is there some advantage of using backgroundworker over a manually created thread like I did?

My goal is to be able to send and receive email from the same web account at the same time (gmail or yahoo) AND to keep the User Interface responsive to update a label as to whats happening in the background and in case the user wants to look at various logs or datagrids or send out a manual report.

If you have an idea on structure to accomplish this that is better than what I did I'd be appreciative!
CodeCruiserCommented:
The main advantage of background worker is that it gives you a structure of events that you can use to do processing in background while also updating progress on the UI without having to go into the details of delegates etc. You would put all your actual code in background worker's DoWork event handler and put progress reporting code (to update labels etc) in ProgressChanged event handler.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
zipnoticAuthor Commented:
Thanks for the thoughts
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.