# 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 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"
Dim mailTimer As System.Timers.Timer
mailTimer.Interval = 18000
mailTimer.Start()


Where Details is the class which is defined as follows:

Class Details
Public UserMailId 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.Port = HostPort
smtpServer.EnableSsl = True
smtpServer.Host = HostName
eMail = New MailMessage()
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 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.

• To your point about backward compatible methods: These become easier to spot if OP removes all Imports Microsoft.VisualBasic.Compatability.VB6 lines from his code. The obsolete code won't compile without a reference to this namespace. Jan 27, 2015 at 13:02
• Good point. Haven't done VB lately ;-) Jan 27, 2015 at 13:04