Archived Forum Post

Index of archived forum posts

Question:

Mailman event OnPercentDone

Aug 29 '13 at 10:17

How can I determine which email message the Mailman event OnPercentDone is referring to?

While sending a quantity of emails, I need to move the files attached to each email once the email has been sent. However I can't figure how to deduce which email has been sent from the OnPercentDone event.

Grateful for any pointers you can give me.

Public Class frmSendEmails  
    Me.BGW_Email = New System.ComponentModel.BackgroundWorker()  
    Me.BGW_Email.WorkerReportsProgress = True  
    Me.BGW_Email.WorkerSupportsCancellation = True  
    .  
    .  
    . 
    Private qEmails As New Queue(Of String)
    Private WithEvents mailman As New Chilkat.MailMan()

        Private Sub btn_Email_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_Email.Click
            me.BGW_Email.RunWorkerAsync()
        End Sub

    Private Sub BGW_EMail_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGW_Email.DoWork

        Dim di As DirectoryInfo
            Dim fi As FileInfo
            Dim fiArr As FileInfo()
            Dim sFolder, sEmail As String  
            Dim email As Chilkat.Email

        mailman.EnableEvents = True
        mailman.SmtpPort = 25
        mailman.SmtpHost = "localhost"

        For Each fi In fiArr

            If BGW_Email.CancellationPending Then
                Throw New Exception("******** User cancelled ********")
                e.Cancel = True
                Exit Sub
            End If

            sEmail = fnGetEmailFromFile(fi.fullname)

            email = New Chilkat.Email()
            email.Subject = dctEmailConfig.Item("EMAIL_SUBJECT")
            email.Body = dctEmailConfig.Item("EMAIL_BODY")
            email.From = dctEmailConfig.Item("EMAIL_FROM")
            email.AddCC(dctEmailConfig.Item("EMAIL_CC"), dctEmailConfig.Item("EMAIL_FROM"))
                        email.AddTo(sEmail, sEmail)
                        mailman.SendEmail(email)

                        bResult = mailman.SendEmail(email)
            If bResult Then
                SyncLock qEmails
                    qEmails.Enqueue(fi.FullName)
                End SyncLock
                        End If
               Next fi
         end sub

         Private Sub mailman_OnPercentDone(ByVal sender As Object, ByVal args As Chilkat.PercentDoneEventArgs) Handles mailman.OnPercentDone

             Dim sDestFolder, sFile As String

             If (args.PercentDone = 100) Then

                 SyncLock qEmails
            sFile = qEmails.Peek()
                    sDestFolder = Path.GetDirectoryName(sFile) & "\Sent"
                    System.IO.File.Move(sFile, sDestFolder)
                    qEmails.Dequeue()
                 End SyncLock

             End If
         End Sub
End Class

Answer

The class "frmSendEmails" contains a single instance of Chilkat.MailMan. Therefore, the "mailman" object can only be sending a single email at a time. When sending email, the Chilkat.MailMan is connected to the SMTP server and the connection is stateful. (See http://www.cknotes.com/?p=40 )

It wouldn't make sense for multiple threads to be attempting to communicate over the same connection to send email at the same time -- because they would interfere with each other. The communications for sending an email have to proceed through an orderly step-by-step process. Once one email is sent, another may begin on the existing connection. However, two emails cannot be sent simultaneously on the same connection. (In general, this applies to all Internet protocols that are stateful: FTP, HTTP, IMAP, POP3, etc. SSH is potentially a bit different because the protocol itself allows for logical channels within the connection.)

Back to your code snippet: It allows multiple threads to attempt to send email simultaneously using the same mailman object instance, but the Chilkat.MailMan is thread-safe, which means that it prevents bad things from happening. It cannot allow simultaneous mail-sending, so when SendEmail is called, another thread's call to SendEmail will be blocked until the current thread's SendEmail returns. At which point the next thread may enter SendEmail, etc.

Therefore, to truly have multiple threads sending email at the same time, you would want each thread to have its own mailman object. If that is the case, then the "sender" in "Private Sub mailman_OnPercentDone(ByVal sender As Object" indicates the mailman object doing the sending.