Uncle Rob
Kilo Patron

But... but... #KillEmail

Yes, kill email when you can. In reality, Some systems and processes may still have components depending on an email initiation.   Here are some examples from my own history.

- support@company.com, service@company.com, contactus@company.com etc addresses that are externally facing need workflow driven responses.   (this is common in the hospitality space)

- legacy system is a starting point and has no rest/soap integration capabilities

- highly specialized staff that, for cultural or practical reasons, only uses email + 1 or 2 specialized tools (traders, field service staff, doctors, lawyers, etc)

Sometimes we have no choice in our inputs, and its better to win small than not win.

Before We Begin

  • Understand Inbound Email Actions, especially Section 6, which outlines how to handle email variables.
  • Understand Service Catalog Script API.   For further research, you can look at the Script Include "Cart" on your dev instance.
  • It is advised that you create your own email address in your environment to handle the intake.   In my example I created "term@company.com".   We ended up creating this such that anyone emailing the address was also sending to company@servicenow.com without realizing it.   In this fashion both the original sender & term@company.com are retained.   A further benefit is you can make separate addresses per workflow you wish to trigger.  
  • Text analysis is your enemy.   As much as possible ensure that your sender automated, not a person.   If that's not possible, resist attempts to make programatic decisions based on user entered email text.

Example:   Email initiated Termination

I've already created a Catalog Item with 3variables: terminee, subject, emailbody (HTML)

I'm assuming that whatever person / system sending will include in the body "priority:high" if priority needs adjustment.

Its also important to note that I don't generally use the request layer, so I will *also* want to modify the sc_req_item

Inbound Action

Name:   Email Based Term

Target Table:   Requested Item [sc_req_item]

Type: New

Order:   Anything lower (numerically) than your existing Incident items

Condition: email.recipients.toLowerCase().indexOf("term@company.com") > -1   (checks to ensure its coming to the controlling email address)

createRequest();

function createRequest() {

  var cart = new Cart();   //calling the cart API

  var item = cart.addItem('eb89a3b937e7d200a2982863b3990eab');   //sys_id of the catalog item I want to fire

  cart.setVariable(item, 'subject', email.subject) //sets catalog variable to the email's subject

  cart.setVariable(item, 'emailbody', email.body_html);   //sets catalog variable to email's body

    var rc = cart.placeOrder();   //this launches the catalog item, and creates a request object.   rc = the request object

  updateRITM(rc.sys_id);   //call a function immediately to update the ritm.   This must be a nested function, otherwise inbound actions get weird.

          //also, we're passing the sys_id of the request so we know what RITM to grab.

}

function updateRITM(req){

  var ritm = new GlideRecord('sc_req_item');

  ritm.addQuery('request', req);   //req is what we passed from the previous function. the sys_id of the request.

  ritm.query();

  while (ritm.next()){

      ritm.u_customer = gs.getUserID();   //my ritm table separately tracks its own customer, since I don't use Request

      ritm.description = email.body_text;   //we're still in the inbound action so why not exploit?

      ritm.priority = email.body.priority;     //good example of how to exploit email body variables

      ritm.update();

  }

}

event.state="stop_processing";   //stop evaluating inbound actions. This is why I keep this record's order lower than my incident from email rules.

Key Take-Aways

  • It is possible, and even handy to trigger workflow from email
  • if you want to modify RITM post insert, use a nested function where-ever you're calling the Cart API
  • Make sure inbound action(s) evaluate before your Incident creation inbound actions
  • Use stop processing once the script is complete.
  • Don't be afraid to exploit email.body.variables... especially if the email source is automated.
25 Comments
ben_hollifield
Tera Guru

Hey rfedoruk - this is a fantastic reference - thanks for putting it together! For folks who really don't want to mess with code, Postmaster on Share will initiate a catalog request from an incoming email. It is less robust than your code solution, though, and offers less customization. It's great to have multiple options available for the various levels of complexity and skill out in the field.


kc99
Giga Expert

Hi rfedoruk,



Can you please expand on the paragraph below as I'm unclear what you mean by 'create your own email address'...



It is advised that you create your own email address in your environment to handle the intake.   In my example I created "term@company.com".   We ended up creating this such that anyone emailing the address was also sending to company@servicenow.com without realizing it.   In this fashion both the original sender & term@company.com are retained.   A further benefit is you can make separate addresses per workflow you wish to trigger.



At the moment we use Office365 accounts alongside SN email account connections and inbound actions to do this sort of thing.



The customers target different Office365 email addresses which are polled via the SN email connections and then processed by the inbound actions.



I'm just concerned that we've missed something fundamental that's OOTB in SN that would help us avoid using Office365 as this method has caused us some issues in the past.



Hope you can help,


Keiron.


Uncle Rob
Kilo Patron

Hey kc99,



The most important thing is that you aren't publicizing a service-now.com email address.   A critical element of long term design is that you make your solutions as easily replaced as possible.   If you tell your organization "use company@service-now.com for terms" then they'll be trying to do so for 100's of years *AFTER* ServiceNow is long gone.   So if you've got a company domain email address as the target, *that*'s the important thing.   Not as important which mechanic gets that email into ServiceNow.



Make more sense?


Chris150
Tera Guru

Rob,



Thanks for posting this it really helped me out.   Everything is working correctly except attachments.



Is there something that I missed?


chedley
Tera Contributor

I noticed that when I use this inbound email rule and I look at the processing the Target and Target table are empty and the logs and details tell me that the inbound rule was skipped - but the new RITM and REQ are actually created and look fine. I see a message in the email log that says 'Skipping [my inbound rule name], did not create or update sc_req_item'.



Any thoughts on this? Seems unusual.


kcolyer002
Kilo Explorer

This is typical when the script field is used to create the record and the 'current' GlideRecord is NOT used to create the record.

 

After typing my response and giving it some thought, I came up with a partial workaround.

What it does not do:

  1. The 'Skipping [my inbound rule name], did not create or update sc_req_item' message will still be logged.

What it does:

  1. Sets the target fields on the email record to point to the newly created record.
  2. Adds an additional log to the email logging the processed status. I have mixed fillings about this since there will then be 2 log statements for the same inbound action.

 

What to do:

Add the following 3 lines at the end of the updateRITM function from the original post:

sys_email.target_table = 'sc_req_item';
sys_email.instance = ritm.sys_id;
logger.log('Processed [your action name], create requested item RITM#');
rajneesh7
Kilo Expert

really nice to see all together and very helpful

Pratuls
Tera Contributor

Can you help me with an idea of how to parse data from the email body to populate catalog form fields?

Uncle Rob
Kilo Patron

This article should help.

Inbound actions assumes name:value pairs inside the email text.  So where it finds them it makes them accessible as email body variables.  IN your inbound script this could be something like....

current.variables.whatever = email.body.thing;

kjain
Giga Expert

Hello @Robert Fedoruk ,

This has really helped me a lot thank you for this blog.

I want to add the email subject and body to the Request form and also catalog task form  fields short description and description how can I achieve this in addition to the code mentioned by you.

Thanks!

Komal