How can we help?

Trigger scripts writing and testing


Triggers are custom actions you can configure when a message is received or changes state. This page details how to write and test trigger scripts.

Triggers are a part of the Auron SMS Server message bus. You can find more information on how to configure triggers here.

This page describes:

Trigger basics

A trigger has these main parts:

  • The message type. The trigger only applies to messages of this type;
  • On status. The trigger runs when a message reaches this status;
  • A condition. A SQL expression that must be true for the trigger to run;
  • The trigger script. This is the script that runs when the condition is true.

The trigger script must be either:

  • VBScript;
  • JavaScript;
  • SQL Script.

For most cases there’s a trigger template available. If there’s no trigger template you can either create a new trigger or create one from a template to customize it.

Trigger scripts always run in sequence according to the processing order of all triggers.

Writing a JavaScript or VBScript trigger

JavaScript and VBScript (Visual Basic Script) triggers are similar in that they both run using the Microsoft Active Scripting engine. This means that in-spite of having a different syntax they have roughly the same abilities.

You can learn more about JavaScript and VBScript in general on W3Schools.

An empty trigger script always has the same structure:

STR_DEBUGFILE       = "C:\ProgramData\Auron\Log\TriggerName.txt"
B_ENABLE_DEBUG      = true

// ========================================================================
// Function: ProcessMessageEx
// ------------------------------------------------------------------------
// ProcessMessageEx trigger function to process incoming messages
// ========================================================================
function ProcessMessageEx(objMessageIn, objMessageDB, dctContext)
{
  Log(">> ProcessMessageEx")

  // ... Your logic here

  Log("<< ProcessMessageEx")
}
CONST STR_DEBUGFILE     = "C:\ProgramData\Auron\Log\TriggerName.txt"
CONST B_ENABLE_DEBUG    = True

' // ========================================================================
' // Function: ProcessMessageEx
' // ------------------------------------------------------------------------
' // ProcessMessageEx trigger function to process incoming messages
' // ========================================================================
Function ProcessMessageEx(objMessageIn, objMessageDB, dctContext)

  Log ">> ProcessMessageEx"

  ' ... Your logic here 

  Log "<< ProcessMessageEx"

End Function

The top two lines declare if logging (debug) is enabled as well as the location of the log file.

The service calls ProcessMessageEx for each message that matches the trigger condition.

You can use the top of the trigger script to initialize variables that you’re going to reuse in ProcessMessageEx for each message.

The arguments to ProcessMessageEx are:

  • objMessageIn. This is the message object that triggered this trigger. Which specific message object depends on the trigger message type. They are listed below;
  • objMessageDB. This is an instance of MessageDB. This object gives access to the message database so you can create new messages or run queries against it;
  • dctContext. This is simply a dictionary object that you can use for keeping variables between different calls to ProcessMessageEx. You can also keep variables between calls to ProcessMessageEx in the global scope of the script.

The objMessageIn is always of type:

The trigger script reloads and re-initializes when:

  • The Auron SMS Server service starts;
  • The trigger script or the trigger configuration is modified.
Include files

You can add a number of include files to your trigger. By default there’s always the ‘common’ include file (‘common.vbs’ or ‘common.js’) that defines the log function but you can add your own as well.

If you’ve made modifications to the ‘common’ include file the setup won’t replace it on an update.

The list of include files is appended to the trigger script in memory right before running the script when starting the service. In case of an error the line numbers are corrected in the error message.

Logging debug output

Use the Log function to log information to a debug file. The two constants at the top of the script file determine the logging behavior:

  • STR_DEBUGFILE Contains the log file destination path;
  • B_ENABLE_DEBUG Set this to false to disable logging.
Creating new messages (SMS or E-mail)

Create a new SMS or E-mail message directly from a trigger by using the local API.

Any of the Local API object can be freely used in trigger scripts.

How to create a new SMS:

// ProcessMessageEx delivers an instance of objMessageDB that already
// has a connection. Using that instance performs better than creating
// a new instance.
// 
// objMessageDB = new ActiveXObject("AxMmServer.MessageDB")

objSms = objMessageDB.Create("SMS")
objSms.ToAddress = "+31611223344"
objSms.Body = "Hello, World!"
objSms.ChannelID = ""   // Specify a channel or depend on the router
objMessageDB.Save(objSms)
' ProcessMessageEx delivers an instance of objMessageDB that already
' has a connection. Using that instance performs better than creating
' a new instance.
'
' Set objMessageDB = CreateObject("AxMmServer.MessageDB")

Set objSms = objMessageDB.Create("SMS")
objSms.ToAddress = "+31611223344"
objSms.Body = "Hello, World!"
objSms.ChannelID = ""   ' Specify a channel or depend on the router
objMessageDB.Save(objSms)

How to create a new E-mail:

// ProcessMessageEx delivers an instance of objMessageDB that already
// has a connection. Using that instance performs better than creating
// a new instance.
// 
// objMessageDB = new ActiveXObject("AxMmServer.MessageDB")

objEmail = objMessageDB.Create("EMAIL")
objEmail.ToAddress = "alerting@company.com"
objEmail.BodyPlainText = "Hello, World!"
objEmail.ChannelID = ""   // Specify a channel or depend on the router
objMessageDB.Save(objEmail)
' ProcessMessageEx delivers an instance of objMessageDB that already
' has a connection. Using that instance performs better than creating
' a new instance.
'
' Set objMessageDB = CreateObject("AxMmServer.MessageDB")

Set objEmail = objMessageDB.Create("EMAIL")
objEmail.ToAddress = "alerting@company.com"
objEmail.BodyPlainText = "Hello, World!"
objEmail.ChannelID = ""   ' Specify a channel or depend on the router
objMessageDB.Save(objEmail)
Opening and creating files

For file access you can use the Scripting.FileSystemObject. This is a default part of Windows.

To write a string to file:

objFso = new ActiveXObject("Scripting.FileSystemObject")

// Arguments are: File path, Overwrite?, Unicode?
objFile = objFso.CreateTextFile("test.txt", true, true)
objFile.WriteLine("This is surprisingly easy ?")
objFile.Close()
Set objFso = CreateObject("Scripting.FileSystemObject")

' Arguments are: File path, Overwrite?, Unicode?
Set objFile = objFso.CreateTextFile("test.txt", True, True)
objFile.WriteLine "This is surprisingly easy ?"
objFile.Close

If you want to read a file into a string without using the file channel:

objFso = new ActiveXObject("Scripting.FileSystemObject")

// Arguments are: File path, IoMode, Create?, Format
// IoMode: 1=Read, 2=Write, 8=Append
// Format: -2=Default, -1=Unicode, 0=ASCII
objFile = objFso.OpenTextFile("test.txt", 1, false, -1)
sText = objFile.ReadAll()
Set objFso = CreateObject("Scripting.FileSystemObject")

' Arguments are: File path, IoMode, Create?, Format
' IoMode: 1=Read, 2=Write, 8=Append
' Format: -2=Default, -1=Unicode, 0=ASCII
Set objFile = objFso.OpenTextFile("test.txt", 1, False, -1)
sText = objFile.ReadAll()
Calling external HTTP API’s

Use the well known Windows HTTPXML API for making HTTP API calls.

An example of a simple HTTP GET request:

objHttp = new ActiveXObject("MSXML2.ServerXMLHTTP") 
  
// arguments are: Verb, Url, Async, (opt)User, (opt)Password
objHttp.open("GET", "https://www.auronsoftware.com/fortune/", false)
objHttp.send()
sResult = objHttp.responseText
Set objHttp = CreateObject("MSXML2.ServerXMLHTTP") 
  
' arguments are: Verb, Url, Async, (opt)User, (opt)Password
objHttp.open "GET", "https://www.auronsoftware.com/fortune/", false
objHttp.send()
sResult = objHttp.responseText

An example of a more elaborate POST request with authorization header:

objHttp = new ActiveXObject("MSXML2.ServerXMLHTTP") 

// arguments are: Verb, Url, Async, (opt)User, (opt)Password
objHttp.open("POST", "https://www.auronsoftware.com/fortune/", false)
objHttp.setRequestHeader("Content-Type", "application/json")
objHttp.setRequestHeader("Authorization", "{BEARER TOKEN}")
objHttp.send("{\"json\": \"values\"}")
sResult = objHttp.responseText
Set objHttp = CreateObject("MSXML2.ServerXMLHTTP") 

' arguments are: Verb, Url, Async, (opt)User, (opt)Password
objHttp.open "POST", "https://www.auronsoftware.com/fortune/", false
objHttp.setRequestHeader "Content-Type", "application/json"
objHttp.setRequestHeader "Authorization", "{BEARER TOKEN}"
objHttp.send("{""json"": ""values""}")
sResult = objHttp.responseText

If your API uses OAuth2 you can authorize using the OAuth2 Authorizer and use the OAuth2 API to refresh your bearer token when/if required.

Connecting to an external database

Use the Windows ADODB objects to connect to an external database from your trigger.

For example to handle an unsubscribe message you could do this:

objDatabase = new ActiveXObject("ADODB.Connection")

// The ADO connection string for your external database
sCs = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=students.mdb"
objDatabase.Open(sCs)

// Parameterized update; better resistance against malicious input
// Say this is an incoming unsubscribe message and we're updating the database
// The e-mail address to update would be the FromAdress from the objMessageIn
// provided by the ProcessMessageEx function
sFromEmail = "alice@school.com" // objMessageIn.FromAddress

objCmd = new ActiveXObject("ADODB.Command")
objCmd.ActiveConnection = objDatabase

// Arguments are: Name, Type, Direction, Size
// Find type values here:
// https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
// Find direction values here:
// https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/parameterdirectionenum
objParam = objCmd.CreateParameter("@eml", 200, 1, 255, sFromEmail)
objCmd.Parameters.Append(objParam)

objCmd.CommandText = "UPDATE Students SET Subscribed = 0 WHERE Email = @eml"
objCmd.Execute()

objDatabase.Close()
Set objDatabase = CreateObject("ADODB.Connection")

' The ADO connection string for your external database
sCs = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=students.mdb"
objDatabase.Open sCs

' Parameterized update; better resistance against malicious input
' Say this is an incoming unsubscribe message and we're updating the database
' The e-mail address to update would be the FromAdress from the objMessageIn
' provided by the ProcessMessageEx function
sFromEmail = "alice@school.com" 'objMessageIn.FromAddress

Set objCmd = CreateObject("ADODB.Command")
objCmd.ActiveConnection = objDatabase

' Arguments are: Name, Type, Direction, Size
' Find type values here:
' https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
' Find direction values here:
' https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/parameterdirectionenum
Set objParam = objCmd.CreateParameter("@eml", 200, 1, 255, sFromEmail)
objCmd.Parameters.Append(objParam)

objCmd.CommandText = "UPDATE Students SET Subscribed = 0 WHERE Email = @eml"
objCmd.Execute()

objDatabase.Close

Or use something like this if you just need to select a value from your database:

objDatabase = new ActiveXObject("ADODB.Connection")

// The ADO connection string for your external database
sCs = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=students.mdb"
objDatabase.Open(sCs)

sName = ""
sQ = "SELECT Name FROM Students WHERE Email = 'alice@school.com'"
objRs = objDatabase.Execute(sQ)
if (!objRs.EOF)
{ 
  sName = objRs("Name").Value
}

// sName is now the name of the student

objDatabase.Close()
Set objDatabase = CreateObject("ADODB.Connection")

' The ADO connection string for your external database
sCs = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=students.mdb"
objDatabase.Open sCs

sName = ""
sQ = "SELECT Name FROM Students WHERE Email = 'alice@school.com'"
Set objRs = objDatabase.Execute(sQ)
If Not objRs.EOF Then
  sName = objRs("Name").Value
End If

' sName is now the name of the student

objDatabase.Close
Opening a MS Excel sheet

Excel sheets works exactly like a database by using the Windows ADODB objects. When your tables have names you can just select from them and update them.

This is an example of how to handle an unsubscribe if you table was in excel instead of a database:

objCon = new ActiveXObject("ADODB.Connection")

objCon.Open("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=Students.xls;" +
  " Extended Properties='Excel 12.0 Xml; HDR=YES'")

// Parameterized update; better resistance against malicious input
// Say this is an incoming unsubscribe message and we're updating the database
// The phone numbers to update would be the FromAdress from the objMessageIn
// provided by the ProcessMessageEx function
sFromNumber = "+31612345678" // objMessageIn.FromAddress

objCmd = new ActiveXObject("ADODB.Command")
objCmd.ActiveConnection = objCon

// Arguments are: Name, Type, Direction, Size
// Find type values here:
// https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
// Find direction values here:
// https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/parameterdirectionenum
objParam = objCmd.CreateParameter("@nr", 200, 1, -1, sFromNumber)
objCmd.Parameters.Append(objParam)

objCmd.CommandText = "UPDATE Students SET Subscribed = 1 WHERE [Phone nr] = @nr"
objCmd.Execute()

objCon.Close()
Set objCon = CreateObject("ADODB.Connection")

objCon.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=Students.xls;" & _
  " Extended Properties='Excel 12.0 Xml; HDR=YES'"

' Parameterized update; better resistance against malicious input
' Say this is an incoming unsubscribe message and we're updating the database
' The phone number to update would be the FromAdress from the objMessageIn
' provided by the ProcessMessageEx function
sFromNumber = "+31612345678" 'objMessageIn.FromAddress

Set objCmd = CreateObject("ADODB.Command")
objCmd.ActiveConnection = objCon

' Arguments are: Name, Type, Direction, Size
' Find type values here:
' https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
' Find direction values here:
' https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/parameterdirectionenum
Set objParam = objCmd.CreateParameter("@nr", 200, 1, -1, sFromNumber)
objCmd.Parameters.Append(objParam)

objCmd.CommandText = "UPDATE Students SET Subscribed = 1 WHERE [Phone nr] = @nr"
objCmd.Execute()

objCon.Close

Or use something like this if you just need to select a value from your Excel sheet:

objCon = new ActiveXObject("ADODB.Connection")

objCon.Open("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=Students.xls;" +
  " Extended Properties='Excel 12.0 Xml; HDR=YES'")

// Use brackets [] if a fiel or table name has spaces or special characters
q = "SELECT Name FROM Students WHERE [Phone nr] = '+31687654321'"
objRs = objCon.Execute(q)

sName = ""
if (!objRs.EOF)
{  
  sName = objRs("Name").Value
}

// sName holds the name of the student

objCon.Close()
Set objCon = CreateObject("ADODB.Connection")

objCon.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=Students.xls;" & _
  " Extended Properties='Excel 12.0 Xml; HDR=YES'"

' Use brackets [] if a fiel or table name has spaces or special characters
q = "SELECT Name FROM Students WHERE [Phone nr] = '+31687654321'"
Set objRs = objCon.Execute(q)

sName = ""
If Not objRs.EOF Then
  sName = objRs("Name").Value
End If

' sName holds the name of the student

objCon.Close

Writing a SQL trigger script

The SMS Server already has a database connection open and therefore is able to optimize the execution of a SQL script to a great extend.

There’s no structure to a SQL trigger script as there is to JavaScript or VBScript triggers.

It can be a multi-line script, a single update or insert statement or a stored procedure call.

You can use any of the message variables in your trigger script by using the field name prefixed with ‘@fld’.

For example, this can be a SQL trigger script that handles an unsubscribe message:

 -- @fldFromAddress is set by the SMS Server service to the value of 'FromAddress'
 -- As an additional optimization the SMS Server only initializes values that you
 -- actually reference in the SQL script.

UPDATE dbStudents.dbo.tblStudents SET subscribed = 0 WHERE EmailAddress = @fldFromAddress

Another example forwards an incoming SMS to an e-mail message using the ‘InsertEmail‘ view:

INSERT INTO InsertEmail(StatusID, ToAddress, Subject, BodyPlainText) VALUES
  ("SCHEDULED", "alert@yourcompany.com", "SMS from: " + @fldFromAddress, @fldBody)

Testing your triggers

With the SMS Server it’s easy to test your triggers. The following sections describe some of the tools you can use.

The trigger activity view

Triggers automatically reload after you modify either the definition or the script file itself.

For JavaScript and VBScript triggers this means a basic syntax check every time you hit ‘ctrl-s’ in your editor.

Therefore it makes sense to keep an eye on the trigger activity view while you’re editing your script.

SMS Server Manager - Trigger activity view

SMS Server Manager – Trigger activity view

Create incoming messages and reprocess them

You don’t need to spend credits to test your trigger. You can simply create an incoming message and reprocess it until your trigger works.

Find out how to create message from the manager application here. Make sure you select ‘In’ as your direction and click ‘Create’.

SMS Server Manager - Create an incoming SMS

SMS Server Manager – Create an incoming SMS

This causes triggers on incoming SMS messages to run on this message.

To continue testing with this same message just right-click on the message and select ‘Reprocess’. Reprocess clears the processed status and causes triggers to run again for this message.

SMS Server Manager - Reprocess

SMS Server Manager – Reprocess

If you’re testing different states that ‘Received’ you can create a message and modify its state in much the same way. Just right-click the message, select ‘Update message status’ and select the status you need to test.

The message trace tab

Every message keeps its own history in the ‘Trace’ field of the message. This is extremely useful when writing or testing scripts.

SMS Server Manager - Message trace

SMS Server Manager – Message trace

The message trace shows the trigger status and which triggers ran on this message. If there was an error it shows the details of the error. Every message type always has this trace tab.

You can add custom trace messages from your trigger by calling the ‘AddTrace‘ method on a message.

The trigger log file

JavaScript and VBScript triggers have the option to keep a log file. The full path of which is at the top of the trigger file.