Inbound Actions

Managing inbound actions can be a nightmare. I often see the out-of-box inbound actions duplicated and modified. The duplication is not really the problem as such because we do require 3 inbound action per table we want to handle inbound emails for.

The problem is that nobody seems to consider centralizing the code so you only need to maintain the code in one place. The worst example I have seen the same code has been duplicated 200 times and if for some reason there is a change in how the emails should be registered all 200 inbound actions needs to be updated.

So I have designed a model for how I propose new inbound actions should be managed.

The code is based on the out-of-box inbound actions for create and update incident (“Create Incident”, “Update Incident” & “Create Incident (Forwarded)”).

The reply inbound action

This is how I would create the inbound action for new

(function runAction( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {

  new global.InboundActionHelper().newEmail(current, event, email, logger, classifier);

})(current, event, email, logger, classifier);

The update inbound action

(function runAction( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {

  new global.InboundActionHelper().replyEmail(current, event, email, logger, classifier);

})(current, event, email, logger, classifier);

The forward inbound action

(function forwardEmail( /*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {

  new global.InboundActionHelper().newEmail(current, event, email, logger, classifier);

})(current, event, email, logger, classifier);

The script include

And then all the code would be in the script include, this code could be made more shorter. For example a lot of the code in new and forward is the same code and could be moved to a common function that is executed for both reducing the redundant code. Leaving only the code that really is specific for new, forward and reply in the specific functions.

var InboundActionHelper = Class.create();
InboundActionHelper.prototype = {
  initialize: function () {
  },

  newEmail: function (current, event, email, logger, classifier) {
    current.caller_id = gs.getUserID();
    current.comments = "received from: " + email.origemail + "\n\n" + email.body_text;
    current.short_description = email.subject;
    current.category = "inquiry";
    current.incident_state = IncidentState.NEW;
    current.notify = 2;
    current.contact_type = "email";

    if (email.body.assign != undefined)
      current.assigned_to = email.body.assign;

    if (email.importance != undefined) {
      if (email.importance.toLowerCase() == "high") {
        current.impact = 1;
        current.urgency = 1;
      }
    }
    current.insert();
  },

  replyEmail: function () {
    gs.include('validators');

    if (current.getTableName() == "incident") {
      current.comments = "reply from: " + email.origemail + "\n\n" + email.body_text;

      if (gs.hasRole("itil")) {
        if (email.body.assign != undefined)
          current.assigned_to = email.body.assign;

        if (email.body.priority != undefined && isNumeric(email.body.priority))
          current.priority = email.body.priority;
      }

      current.update();
    }
  },

  forwardEmail: function () {
    current.caller_id = gs.getUserID();
    current.comments = "forwarded by: " + email.origemail + "\n\n" + email.body_text;
    current.short_description = email.subject;

    current.category = "inquiry";
    current.incident_state = IncidentState.NEW;
    current.notify = 2;
    current.contact_type = "email";

    if (email.body.assign != undefined)
      current.assigned_to = email.body.assign;

    current.insert();
  },

  type: 'InboundActionHelper'
};

Why do this

As you can see the inbound actions are very similar and since servicenow have initilized current with the target table you can use that to determine what other actions you need to do in case you have to something special if email is coming from someone specific, sent to a specific email or contans certain words etc.

All the code is centralized in the script include so it will be much easier to make a general change to all inbound actions just by editing in one place.

Another advantage of this is it will be easier to implement a method of testing inbound actions in test instead of in prod. Many times a customer got several email adresses and the cases created is often assigned based on the email address the email was sent to. This can only truely be tested in prod as there is only one email address and that is redirected to the prod instance. Instead one could implement a test model that simulates email was sent to a specific address be looking at who sent it. So if user A sent the email then treat the email as if it was sent to email1@domain.com if the email was sent bu user B then treat the email as if it was sent o email2@domain.com etc.

Suggestions

Suggestions are welcome. I hope developers will start adopt this idea/model so customes can have a manageable set of inbound actions.

Leave a comment