Enumeration of field values in email body

RobertBarnes
Mega Contributor

The documentation and posts I have seen assume that the name of the field is known when retrieving value from the email body, for example.

  [code]

  if(email.body.foo != undefined) {
      current.u_my_field = email.body.foo;
}

[/code]

 

Is it possible to possible to retrieve the field names and values through a collection or other type of enumeration similar to:

[code]

var x = 0;

while ( x < email.body.length )   {
    var name = email.body[x].name;
    var value = email.body[x].value;
}

[/code]

 

 

 

 

 

 

1 ACCEPTED SOLUTION

tltoulson
Kilo Sage

Hi Robert,



You could possibly access the names dynamically by iterating through the properties of email.body.   You would still need some way of mapping the property name to the field name of your choice.   The easiest way to do this is likely through convention.   Here's the method:



var prop,


        searchProp,


        gr;



// Iterate through each property (foo for example) in the email.body object (You may need to restrict this if body has properties/functions other than those parsed from the email)


for (prop in email.body) {


        // First we will assume the convention that spaces are automatically replaced with underscores, so we will reverse it


        searchProp = prop.replace('_',' ');



        // Now we can use sys_documentation to map a field Label to its underlying field name


        gr = new GlideRecord('sys_documentation');


        gr.addQuery('name', 'TABLE NAME HERE');


        gr.addQuery('label', searchProp);


        gr.setLimit(1);


        gr.query();


        // If a Label record is found


        if (gr.next()) {


                  // Use the element field (underlying field name) to set the value dynamically


                  current[gr.element] = email.body[prop];   // This line is functionally equivalent to current.u_my_field = email.body.foo


        }


}



You may need to do some testing and modifying to get this to work right, I haven't tested it though I've done something similar.   Also, be aware that this means you absolutely want to check your security as ANY field on the table could be populated if the user knows the Label name.



HOW IT WORKS:


Lets say in an inbound email, a user has placed the following:



Short Description: This gets applied to the short_description field


Wrong: This will do nothing as no field will have the label wrong unless you created one


Active: false



First, the inbound email will create email.body.short_description, email.body.wrong, and email.body.active.   The for loop above will iterate through these values.   The process will of something like this:



Set prop to 'short_description'


        Set searchProp to 'short description' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'short description'


        Get value of gr.element which is 'short_description'


        Set current.short_description (current[gr.element]) to email.body.short_description (email.body[prop])


Set prop to 'wrong'


        Set searchProp to 'wrong' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'wrong'


        No records found, so ignore this field


Set prop to 'active'


        Set searchProp to 'active' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'active'


        Get value of gr.element which is 'false' (this could be bad if your security doesn't prevent this update)


        Set current.active (current[gr.element]) to email.body.active (email.body[prop])



So this creates a much more dynamic, and much shorter script for setting the fields but it also comes with the risk of allowing users to potentially set any field... test this heavily.


View solution in original post

4 REPLIES 4

RobertBarnes
Mega Contributor

Can script be used to enumerate field:value   tags in the email body?


Is there a collection or other object that can be referenced?


Is there a work around, short of explicitly hard-coded each field in the script as shown in the original question?


tltoulson
Kilo Sage

Hi Robert,



You could possibly access the names dynamically by iterating through the properties of email.body.   You would still need some way of mapping the property name to the field name of your choice.   The easiest way to do this is likely through convention.   Here's the method:



var prop,


        searchProp,


        gr;



// Iterate through each property (foo for example) in the email.body object (You may need to restrict this if body has properties/functions other than those parsed from the email)


for (prop in email.body) {


        // First we will assume the convention that spaces are automatically replaced with underscores, so we will reverse it


        searchProp = prop.replace('_',' ');



        // Now we can use sys_documentation to map a field Label to its underlying field name


        gr = new GlideRecord('sys_documentation');


        gr.addQuery('name', 'TABLE NAME HERE');


        gr.addQuery('label', searchProp);


        gr.setLimit(1);


        gr.query();


        // If a Label record is found


        if (gr.next()) {


                  // Use the element field (underlying field name) to set the value dynamically


                  current[gr.element] = email.body[prop];   // This line is functionally equivalent to current.u_my_field = email.body.foo


        }


}



You may need to do some testing and modifying to get this to work right, I haven't tested it though I've done something similar.   Also, be aware that this means you absolutely want to check your security as ANY field on the table could be populated if the user knows the Label name.



HOW IT WORKS:


Lets say in an inbound email, a user has placed the following:



Short Description: This gets applied to the short_description field


Wrong: This will do nothing as no field will have the label wrong unless you created one


Active: false



First, the inbound email will create email.body.short_description, email.body.wrong, and email.body.active.   The for loop above will iterate through these values.   The process will of something like this:



Set prop to 'short_description'


        Set searchProp to 'short description' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'short description'


        Get value of gr.element which is 'short_description'


        Set current.short_description (current[gr.element]) to email.body.short_description (email.body[prop])


Set prop to 'wrong'


        Set searchProp to 'wrong' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'wrong'


        No records found, so ignore this field


Set prop to 'active'


        Set searchProp to 'active' by replacing underscores


        Query sys_documentation for a record on the 'TABLE NAME HERE' table where the label is 'active'


        Get value of gr.element which is 'false' (this could be bad if your security doesn't prevent this update)


        Set current.active (current[gr.element]) to email.body.active (email.body[prop])



So this creates a much more dynamic, and much shorter script for setting the fields but it also comes with the risk of allowing users to potentially set any field... test this heavily.


This is an excellent code snippet and explanation Travis.



One minor improvement is to add the below immediately inside the for loop


if (!email.body.hasOwnProperty(prop)) continue;



and you might save yourself an error or two


Thanks Travis that's a good solution that provides the functionality I was looking for.   And thanks also for the supporting documentation. I will also add the check as suggested by Andrew.