Passing arguments to a SendMail function referenced by addressOf operator I am trying to send daily mail alert to users based on some timer values. For that I've used Addhandler to call the sendmail() function on timer Tick. In this scenario I faced a problem and I am unable to pass arguments to the function through AddressOf.

What I wanted was to use my function, which took these parameters…

 Public Sub SendMail(ByVal UserMailId As String,
                     ByVal UserPassword As String,
                     ByVal HostName As String,
                     ByVal HostPort As String)


by calling it using AddHandler mailTimer.Elapsed, AddressOf userDetails.SendMail(parameters), but that failed with an error:


  'AddressOf' Operand name must be the name of the method without
  parenthesis


After some research, here's my solution for this problem:

Dim userDetails As New Details
' These values are from database that will changed based on some conditions given
' now it is hardcoded for an example
userDetails.HostName = "smtp.gmail.com"
userDetails.HostPort = "587"
userDetails.UserMailId = "mailuser@gmail.com"
userDetails.UserPassword = "mymailPasswo6d"
Dim mailTimer As System.Timers.Timer
mailTimer.Interval = 18000
AddHandler mailTimer.Elapsed, AddressOf userDetails.SendMail
mailTimer.Start()


Where Details is the class which is defined as follows:

Class Details
        Public UserMailId As String
        Public UserPassword As String
        Public HostName As String
        Public HostPort As String
        Public Sub SendMail()
            Try
                Dim smtpServer As New SmtpClient
                Dim eMail As New MailMessage()
                smtpServer.UseDefaultCredentials = False
                smtpServer.Credentials = New Net.NetworkCredential(UserMailId, UserPassword)
                smtpServer.Port = HostPort
                smtpServer.EnableSsl = True
                smtpServer.Host = HostName
                eMail = New MailMessage()
                eMail.From = New MailAddress(UserMailId)
                eMail.To.Add(txtemailTo.Text)
                eMail.Subject = "Test Mail"
                eMail.IsBodyHtml = False
                eMail.Body = txtMessage.Text
                smtpServer.Send(eMail)
                MsgBox("Mail Sent")
            Catch errorT As Exception
                MsgBox(errorT.ToString)
            End Try
        End Sub
    End Class


Now what my question is:


Is the method I was using the correct one? Is there any simple or alternate solution for this?
Can anyone please review the code to improve it? It gives me better results but I think some modification is required.
The System.Timers.Timer.Elapsed event needs a handling method with the signature sender As Object, e As ElapsedEventArgs. This means that any method which you want to assign this event to, by using the AddressOf operator has to have exactly this signature by the meaning of the type and order of the parameters.  

Public Sub MailTimerElapsed(sender As Object, e As ElapsedEventArgs)
    ' the code which should be processed if the timer is elapsed
    ' should be either called here or be placed here
End Sub


If you plan to use the System.Timers.Timer without setting the SynchronizingObject property, you need to know that the event is raised on a ThreadPool thread, so interaction with a UI (at least with setting any value like assigning a value to a Text property of a TextBox) needs to be synchronized by your code.  

Also, if the time needed to finish the codeexecution from the eventhandler exceeds the set Interval it will reentrant if the mentioned property is not set.  

Read more: Timer class  



These fields  


Public UserMailId As String
Public UserPassword As String
Public HostName As String
Public HostPort As String  



should better be properties instead of public variables. You could also consider to pass these values at calling the constructor, and make the fields Private.



You should get used to the NET style. This means calling methods which has been kept for downward compatibility like MsgBox should be avoided and replaced by the MessageBox.Show() method



Instead of placing the eventhandler for the Timer.Elapsed event inside the Details class you should place it in the calss where you create the timer object and call from inside the handler your desired mail sending method.