How to REALLY monitor SMTP, POP3 and IMAP on Exchange 2003

Even though Microsoft Exchange Server 2010 has already been released, many organizations still use Exchange 2003. In this article I’ll explain how to thoroughly monitor the various Internet protocols that Exchange 2003 offers, including SMTP, POP3, IMAP (and NNTP for that matter). The reason why I’ll only be looking at Exchange 2003 is because there is a significant difference in architecture between Exchange 2003 and later versions.

It is a common misconception that you can effectively monitor the W3SVC service (commonly referred to as IIS, though IIS encompasses a lot more than just a web server) and other services provided through IIS, such as SMTP and POP3, by simply monitoring their associated service. It’s a misconception, because a given IIS-based service may contain multiple instances – most commonly the case with the World Wide Web Service which often hosts multiple independent web sites. The status of these instances can be controlled independently of the hosting service, though that service needs to be running of course.

Don’t despair though, most server-based windows applications, fortunately, can be monitored by ensuring that their respective service is – well – running. For example, to ensure that the Apache service is up, you “simply” make sure that the Apache service is running. The same goes for countless other services such as MySQL – even SQL Server (of course you can still detach individual databases in SQL Server).

Exchange 2003, due its partnership with the Internet Information Services 6.0, is different though. Yes, IIS and Exchange 2003 are tightly coupled, and if you intend to have your Exchange Server 2003 communicate with any other server using a standard Internet protocol such as SMTP, then you will need IIS.

eventlogblog_2010_01_exchange_iis_components.png

The screenshot above shows that the inetinfo.exe process hosts all the major services (bold name), and that each service can host one or more instance. For more details please see http://technet.microsoft.com/en-us/library/bb124674(EXCHG.65).aspx.

The three most common Internet services your Exchange 2003 server is running are probably SMTP, POP3 and IMAP4. While a lot of attention is being paid to the core Exchange services such as

  • Microsoft Exchange Information Store (MSExchangeIS)
  • Microsoft Exchange System Attendant (MSExchangeSA)

The services providing SMTP, POP3 and IMAP4 connectivity are usually similarly important, especially the SMTP service. Looking at the EventSentry service status page immediately reveals that the SMTP, POP3 and IMAP4 services are managed by IIS:

Thumbnail image for eventlogblog_2010_01_es_services.png

As you can see, IMAP4Svc, POP3Svc and SMTPSvc all use inetinfo.exe (Executable column) for their host process. So why is this important again?

Since all of these services support multiple instances INSIDE the service (inetinfo.exe), the host process will continue to run even when one or more instances inside the service are stopped. Since most installations only have one instance, stopping that one instance inside the service will still leave the service up and running. The effect of course is the same; the service is not available to the end users while the Windows service will happily continue to run.

A screen shot from the System Manager application shows instances listed inside:

eventlogblog_2010_01_system_manager.png

As you can see with the IMAP4 protocol, we have two virtual servers setup that are both hosted inside the “Microsoft Exchange IMAP4” service. To stubbornly illustrate my point further I took a screenshot that shows both IMAP4 instances stopped while the service itself is running:

eventlogblog_2010_01_system_manager_services.png

So I think we’re all in agreement now that monitoring the POP3, SMTP etc. services in Exchange 2003 is not enough if you want to ensure that these services are actually available. So how do we monitor all of these instances?
The easiest way is actually with a VBScript, which is included below. VBScript works well since the cscript.exe interpreter is readily installed on Windows 2003, so no additional installation of tools is required. The script enumerates all instances of a given protocol, and checks whether they are running or not. If at least one instance is not running, the tool will return 1, thus setting the ERRORLEVEL to 1.

This VBScript can then be embedded into EventSentry, which will then run the script at set intervals using the application scheduler, notifying you via email (with the proper filter setup) when an instance is stopped. There’s a screencast for that, you can view it at https://www.eventsentry.com/screencasts/eventsentry-application-scheduler/eventsentry-application-scheduler.htm. It shows you how to create an embedded script and setup EventSentry to notify you when the scripts returns an error. Note that the screencast uses an older version of the script which only monitored web sites (not SMTP, IMAP4, …), but the process of setting up the script with EventSentry is exactly the same.

You should be able to use the script as-is, just configure which protocols are monitored by adjusting the values in the “Define which protocols to monitor here” section. The script always prints all installed instances and their status, and any stopped instance is prefixed with an asterisk. Below is what an email from EventSentry looks like:

eventlogblog_2010_01_appscheduler_email.png

The line with the stopped instance won’t be yellow in the actual email, I just added this for readability. The script can also easily be modified to automatically start any stopped instances – simply add the line

Instance.Start

after line 102. This will still trigger an email (or error) to notify you that it was stopped, but a subsequent run of the script at the next monitoring interval should not trigger an error again if the start was successful.

A note of caution here though – I have seen the script hang indefinitely with this line added when an instance that is currently stopped can’t be started because it’s not configured correctly. Hence, it’s not included by default.

‘ Lists the state of all IIS protocols configured on the local machine
‘ and returns an %ERRORLEVEL% of 1, if at least one instance is not in
‘ the “Started” state.

‘ When scheduling this script with EventSentry’s application scheduler,
‘ make sure that the interpreter is set to “cscript.exe”

Option Explicit

Dim allInstancesAreRunning

Dim monitorSMTP, monitorPOP3, monitorIMAP4, monitorNNTP, monitorFTP, monitorWWW

‘ Define which protocols to monitor here

monitorSMTP  = 1
monitorPOP3  = 1
monitorIMAP4 = 1
monitorNNTP  = 1
monitorFTP   = 1
monitorWWW   = 1

‘ Define which protocols to monitor here

‘ ==================== EXECUTION STARTS HERE ====================
allInstancesAreRunning = EnumerateAllInstances

If allInstancesAreRunning = 0 Then
    WScript.Echo vbCRLF & “WARNING: One or more IIS components are not running” & vbCRLF
End If

If allInstancesAreRunning = 0 Then
    WScript.Quit 1
End If

‘ ==================== FUNCTIONS ====================
Function EnumerateAllInstances

EnumerateAllInstances = 1

If monitorSMTP = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “SMTPSVC”)
End If

If monitorPOP3 = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “POP3SVC”)
End If

If monitorIMAP4 = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “IMAP4SVC”)
End If

If monitorNNTP = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “NNTPSVC”)
End If

If monitorFTP = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “FTPSVC”)
End If

If monitorWWW = 1 Then
    EnumerateAllInstances = EnumerateAllInstances And EnumerateInstances(“localhost”, “W3SVC”)
End If

End Function

Function MapServiceToInstance( Service )

    If Service = “SMTPSVC” Then
        MapServiceToInstance = “IIsSmtpServer”
    ElseIf Service = “POP3SVC” Then
        MapServiceToInstance = “IIsPop3Server”
    ElseIf Service = “IMAP4SVC” Then
        MapServiceToInstance = “IIsImapServer”
    ElseIf Service = “W3SVC” Then
        MapServiceToInstance = “IIsWebServer”
    ElseIf Service = “NNTPSVC” Then
        MapServiceToInstance = “IIsNntpServer”
    ElseIf Service = “FTPSVC” Then
        MapServiceToInstance = “IIsFtpServer”
    End If

End Function

Function EnumerateInstances( Server, Service )
    On Error Resume Next
   
    Dim VirtualServerService
    Dim Instance, InstanceID
   
    EnumerateInstances = 1
   
    Set VirtualServerService = GetObject(“IIS://” & Server & “/” & Service)
   
    If Err.Number = 0 Then
        InstanceID = MapServiceToInstance(Service)
       
        For Each Instance in VirtualServerService
         
          If Instance.KeyType = InstanceID Then
             
                  If SiteIsNotRunning(Instance.ServerState) Then
                      WScript.StdOut.Write “*”
                      EnumerateInstances = 0
                  End If
                 
                  WScript.StdOut.Write Instance.ServerComment & ” (” & Service & “): ” & State2Desc(Instance.ServerState) & vbCRLF
          End If
        Next
    End If
   
End Function

Function SiteIsNotRunning( nState )

    If nState <> 2 Then
        SiteIsNotRunning = 1
    Else
        SiteIsNotRunning = 0
    End If
   
End Function

Function State2Desc( nState )

    Select Case nState
    Case 1
        ‘MD_SERVER_STATE_STARTING
        State2Desc = “Starting”
    Case 2
        ‘MD_SERVER_STATE_STARTED
        State2Desc = “Running”
    Case 3
        ‘MD_SERVER_STATE_STOPPING
        State2Desc = “Stopping”
    Case 4
        ‘MD_SERVER_STATE_STOPPED
        State2Desc = “Stopped”
    Case 5
        ‘MD_SERVER_STATE_PAUSING
        State2Desc = “Pausing”
    Case 6
        ‘MD_SERVER_STATE_PAUSED
        State2Desc = “Paused”
    Case 7
        ‘MD_SERVER_STATE_CONTINUING
        State2Desc = “Continuing”
    Case Else
        State2Desc = “Unknown state”
    End Select

End Function

You can also download the script from here.

Until next time,
Ingmar.