Logon Script to Send Email Notifications

A member of the ASP Free Forums recently asked if there was any way to receive email notification whenever users logged on across the network. I responded that there was. Today I’m going to show you how to create a network logon script that will send an email notification whenever a user logs on.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 7
January 29, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement
As I approached this scenario, I immediately saw two ways of accomplishing this task.  I could simply monitor Active Directory for user logon events, but that would require that Active Directory actually be in use.  So, in an effort to make a single solution, I settled upon the second idea.

The idea was to create a logon script.  Since logon scripts are loaded every time a user logs on, it works even when Active Directory is not in use.  I also wanted this script to have the ability to run as a network logon script or as a standalone script for non-networked workstations.  Thus, I had to rely on common objects without assuming any server capabilities.

The script’s functionality was simple.  It needed to log information about the logon event, including user name, machine information, and date/time. Then it needed to create and send an email containing that information to a given address.

Of course, the script should function quietly in the background and require no user interaction.

With these goals in mind, I set out to create the script.  The first order of business was to get all of the required information to create the email.

Let’s start there.

Gathering logon details

You begin by creating functions that gather the required information, such as account name, computer name, and IP addresses.

With scripting techniques, such as WMI, there are literally dozens of ways of retrieving this information.  I’ve elected to use the simplest and most cross-platform compliant variations in order to make this script as universal as possible.  If you have an alternative method that you prefer, you can surely use it as a substitute.  I encourage you to try and find other ways to perform these tasks.

Set WshNetwork = CreateObject("WScript.Network")

Like all of my scripts, I begin with an area to establish global objects, variables, and constants.  This script will have many of each when we’re finished.  For the moment, let’s instantiate the WshNetwork object since we’ll be using it in several of our methods.

Function AccountName

   If IsNull(WshNetwork) Then Set WshNetwork = CreateObject _

       ("WScript.Network")

   AccountName = WshNetwork.UserName

 

End Function

Our first function is quite simple.  We use the WshNetwork object’s UserName property to return the account name for the currently logged on user.  This text string is set as the return value for our function.

Creating reusable code snippets is a great way to save time developing and writing code.  Always keep a repository of frequently used functions and snippets.  Think twice, write once!

Notice how the first line in my function checks for the existence of the WshNetwork object and creates it if it doesn’t find it.  Since we’ve already added that to the beginning of our script, this isn’t necessary.  However, I wanted to ensure that my functions were easily reusable in other scripts.  This allows me to copy and paste this function into another script without having to worry about conflicting with any existing objects.  This is the same reason that I chose to perform each of these tasks in a separate function.

Function ComputerName

   If IsNull(WshNetwork) Then Set WshNetwork = CreateObject _

       ("WScript.Network")

   ComputerName = WshNetwork.ComputerName

 

End Function

Just like the AccountName function, a call to the WshNetwork object’s ComputerName property returns the local machine name.  Once again, we set this as your function’s return value.

Now it’s time to get IP addresses.  This can be a little tricky.  Assuming that the local machine is connected to a network, there could be two different IP addresses: one local network address and a WAN address, if this is a remote workstation.  By retrieving both, we are able to satisfy the needs of nearly any network configuration.

In order to retrieve IP addresses, we’re forced to resort to using WMI.  WMI provides much better access to hardware information than WSH is able to provide natively.

There is one slight caveat to the code I’m providing below.  It only works if the IP address for the network connection is being issued dynamically using DHCP.  This will not work for statically assigned addresses.

If you would still like to see the function for finding a static IP address, please find the link at the bottom of this article to join the discussion.  I’ll be more than happy to provide it there.

This does pose a slight limitation that could be worked around with a function to retrieve static IPs as well.  However, I deemed it a waste of time considering that most networks are using DHCP, and the fact that a network administrator should already know a statically assigned address given a computer name.

Function LAN_IP

   strComputer = "."

   Set objWMIService = GetObject("winmgmts:" _

       & strComputer & "rootcimv2")

   Set colItems = objWMIService.ExecQuery _

      ("Select IPAddress from Win32_NetworkAdapterConfiguration” _

          & ” WHERE IPEnabled=TRUE",,48)

  

   For Each objItem In colItems

       If Not IsNull(objItem.IPAddress) Then

          LAN_IP = objItem.IPAddress(0)

          Exit For

       End If

   Next

 

End Function

This function will return any DHCP-assigned LAN address with the help of WMI.  We first connect to the cimv2 root and then query the Win32_NetworkAdapterConfiguration class.  This class returns objects that represent currently enabled network adapters.

Note that I’ve written this script to return only those adapters using the TCP/IP protocol.  If your network uses some other protocol such as IPX, you’ll need to remove the WHERE IPEnabled=TRUE clause from this query.

A For Each loop processes each object and returns the first listed IP address for each adapter.  This only returns the first IP address for the last adapter found.  This isn’t generally a problem, since there will only be one adapter in most cases.

In the event that you are using more than one adapter, you may wish to add the IP addresses to an array and have the function return as a string of those array elements instead.

Function WAN_IP

   Set objxmlHTTP = CreateObject("Microsoft.XMLHTTP")

   Call objxmlHTTP.open("get", "http://checkip.dyndns.org", False)

   objxmlHTTP.Send()

 

   strHTMLText = objxmlHTTP.ResponseText

   Set objxmlHTTP = Nothing

 

   If strHTMLText <> "" Then

       varStart = InStr(1, strHTMLText, "Current IP Address:", _

          vbTextCompare) + 19

       If varStart Then varStop = InStr(varStart, strHTMLText, _

          "</body>", vbTextCompare)

       If varStart And varStop Then strIP = Mid(strHTMLText, varStart, _

          varStop - varStart)

 

   Else

       strIP = "Unavailable"

 

   End If

   WAN_IP = Trim(strIP)

 

End Function

The function that returns the Wide Area Network address, or public address, is much more involved.  Since there is no way to see this address locally, we must consult an outside source.

DynDNS provides a free web service that identifies the WAN IP address of the machine accessing their web page.  This function requests that web page and then uses a technique known as screen-scraping to read the IP address that was sent back.

For more information about how this works, please refer to part one of my Handling Live Web Content in WSH series here on ASP Free.

Creating and sending the notification email

Now that we have all of the information that we need, it’s time to write a function that will create and send an email with it.  I’ll keep the explanations here brief.  If you would like more information, I have an entire article dedicated to the topic.

Sending Emails Using CDO in WSH

In short, this function needs to create an email message and send it using the details provided.  Most of the details need to be provided as constants at the beginning of the script.  The body of the email will be passed as arguments to the function.

Function SendMail(strBody)

   Set objEmail = CreateObject("CDO.Message")

   With objEmail

       .From = ADMIN_EMAIL

       .To = ADMIN_EMAIL

       .Subject = "Logon Notification"

       .HTMLBody = strBody

The function begins by connecting to the CDO object and assembling the message object to send.  Like any email, it requires a To and From address along with a subject line and body.

       .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2

       .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SMTP_SERVER

       .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTP_PORT

       If USE_AUTHENTICATION Then

          .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1

          .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/sendusername") = SMTP_USER

          .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = SMTP_PASS

 

       End If

       If SMTP_SSL Then

          .Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True

 

       End If

       .Configuration.Fields.Update

The next section of code sets all of the required SMTP server settings for the CDO object to use.  I’ve allowed for both simple and authenticated SMTP access.  Variables at the beginning of the script are used to set these requirements.

       On Error Resume Next

       Err.Clear

 

       .Send

 

       If Err.number <> 0 Then

          SendMail = Err.Description

 

       Else

          SendMail = "The server did not return any errors."

 

       End If

       On Error Goto 0

 

   End With

 

End Function

We end our function by actually sending the email message.  A little error-handling ensures that the script doesn’t break if for some reason the mail cannot be sent.  With a little tweaking, you could easily make this function retry after a period of time, if this were to happen.

Putting it all together

With all of the pieces in place, it’s time to put this all together.  We need to start by setting the necessary variables for the SendMail function.  These should be configured properly before this script is deployed.

' Please indicate where notifications should be sent

Const ADMIN_EMAIL = "recipient@mail.com"

 

' Please provide the following details for your SMTP server

Const SMTP_SERVER = "smtp.mail.com"

Const SMTP_PORT = 25 ' Do not change if you are unsure

 

' If your SMTP server requires authentication, please set

' USE_AUTHENTICATION to True and supply a username and password

Const USE_AUTHENTICATION = False

Const SMTP_USER = "username"

Const SMTP_PASS = "password"

 

' If your SMTP server uses Secure Password Authentication, please

' set the following value to True.

Const SMTP_SSL = False

This code should be at the beginning of your script.  Set any of the necessary constants to ensure that your email will be sent properly.  If you don’t have access to an SMTP server, there are free mail sending services available on the Internet.

Now it’s time to gather our last bit of details and put our email message together.

dteTime = Time

dteDate = Date

Now is a good time to grab the local date and time stamps.  This can be helpful for tracking logons at a later date.

strMessage = "A user has logged onto <b>" & ComputerName & _

      "</b> from <b>" & WAN_IP & _

      "</b> with the following details:<br><br>" _

   & "Logon Date: " & dteDate & "<br>" _

   & "Logon Time: " & dteTime & "<br>" _

   & "Account Name: " & AccountName & "<br>" _

   & "LAN IP: " & LAN_IP & "<br>"

Here we’re simply assembling a text string containing a simple email message with all of the logon details that have been provided by our functions.

result = SendMail(strMessage)

Now we take our message body and pass it to the SendMail function.  This one line does the dirty work.

That’s the concept in a nutshell.  All that’s left is to set this as a logon script on each of your machines.  In a networked environment, this can usually be done from the server.

You can download the full source code for this article below to see the complete script in its entirety.  I’ve also added a little bonus that allows you to debug the script before putting it into general use.

Thanks for reading.  Have some fun with this script.  Until next time, keep coding!

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 1 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials