Some PDIs are currently unavailable, and PDI actions are paused. View the latest updates here. Read More

jason_petty
Tera Expert

The method below was originally published on Oct 25, 2012, is an outdated process

Please see the following post for help! >   Loading data from an email attachment


I had a number of people respond to this post with the same problem and together with my colleague I re-wrote the instructions to make it work.

I had a customer that wanted to have IBM Maximo product send an email to ServiceNow and have a CSV/XLS file attached to the email automatically create a new Data Source, load the data, then transform it all automatically just from receiving the email. Here is what I did to get that to work:


1. Create a Data Source Manually first so you can set up the Import Set Table and the Transform Map that you will use later. This is necessary since you need a Transform Map defined before you send the email inbound to ServiceNow. This Data Source can be deleted after creating the Import Set Table and Transform Map.
2. Get a sample CSV/XLS file and attach it to the Data Source and load the data at least once.
3. Define your Transform Map and set it up so the data is getting transformed into the right table in the format that you need.
4. Create a user that you will use for basic authentication with no roles and has a password.
5. Create a REST Message that points to your own instance for the REST endpoint: https://instancename/sys_import.do as the url named "Inbound Import Set Poster"
6. Check the box for "Use basic auth" and set the username and password from step #4
7. Edit the "get" function and add the following function parameters:

8. Create an Inbound Email Action with the following settings:

HERE IS THE CODE TO COPY:



if (current.getTableName() == "sys_data_source") {

      current.name = email.subject.substring(3);
      current.import_set_table_label = email.body.import_set_table_label;
      current.import_set_table_name = email.body.import_set_table_name;
      current.file_retrieval_method = email.body.file_retrieval_method;
      current.format = email.body.format;

      current.update();

var r = new RESTMessage('Inbound Import Set Poster', 'get');
r.setStringParameter('tableLabel', encodeURIComponent(current.name));
r.setStringParameter('customDataSource', current.sys_id);
              r.setStringParameter('tableName', current.import_set_table_name);
r.execute();
}


9. The Condition can be anything you want but the Target table needs to be sys_data_source.
10. Enable the inbound email settings in your instance to receive email and process them. See WIKI http://wiki.servicenow.com/index.php?title=Configuring_Email for this.
11. Now send an email like this to the email instancename@unix.service-now.com (The "unix" part of this avoids any email formatting issues with email clients):

  1. To: instancename@unix.service-now.com
  2. Subject: DS:Test Data Source 1
  3. Body:


              import_set_table_label:Test Import Set Table
              import_set_table_name:u_test_import_set_table
              file_retrieval_method:Attachment
              format:CSV

NOTE: CSV would be Excel if you are using an XLS file

12. Wait until the email is processed and it should have created your Data Source with whatever is after the "DS:" in the subject
13. Make sure the import_set_table_name is set to whatever you named your import set table when you created your Data Source in step 1 (This is very important since the Transform Map is linked to this table)
14. The format is set to either Excel or CSV.
15. You need to attach the file you want to attach to the Data Source.

>


The method above was originally published on Oct 25, 2012, is an outdated process

Please see the following post for help! >   Loading data from an email attachment


68 Comments
payerle
Tera Contributor

Yeah, same here.   My first thought process was; use a onBefore transform script that would mark them as Installed, and then do target.update();


Then I would have an onComplete script that would search for any items that weren't updated [today()] or now(), to get the today's date.   And IF it wasn't updated today, then change the status to "retired".



For the life of me, I can't get the statement right, I think the logic is there, but also having trouble because it will mark them as installed, but then the onComplete script overwrites and marks everything as "retired"   so it works, then it reverts midway.   Blah!


payerle
Tera Contributor

Is it a CSV or excel?   I had trouble with excel files.   Have you done the other steps?   I found doing a manual import and walk through helped because it ensured all other steps worked properly.   The inbound action just automated that for me.   SO if the manual steps aren't working, then I would start there and figure out what broke, and then go back to your inbound action.


Tom Brown
Giga Guru

If you always import on "Fridays" or some such, you could set a scheduled job to do it that night perhaps.   I don't care for that approach since if your import fails for some reason, everything would get marked as retired.   I'd rather tie it to the fact that the import happened.


Tom Brown
Giga Guru

You've probably already done a lot of troubleshooting like this, but if you haven't tried it, run a "fix script" with your query after your import is complete, just to see what you're returning on that GlideRecord query about items not updated "today".   If you can get the fix script to spit out the right answers, then try the script after completion, either by a BR or OnComplete.


payerle
Tera Contributor

This sounds like a great idea - I'm not familiar with the 'fix script' do you have a sample I can follow?


Tom Brown
Giga Guru

Fix scripts are like background scripts, except that they are stored and you can see more diagnostic information.   Also very similar to a scheduled job, except that you can use gs.print to show variable contents and messages.   It's a great place to test your scripts and keep them for later.   If you look for Steve Bell's work, sabell2012 , he's got some really good stuff on GlideRecord queries and promotes use of Fix Scripts for development and testing.   If you get to visit a Knowledge event, I'd encourage you to sign up for one of his labs.  



Anyway, type 'fix script' in the navigator and it should take you there.   Click 'New', put in some code, click the 'run fix script' link below the 'script' box, and see what it does.   It's live, so be sure to verify before doing something that will write a bunch of data back.   It does seem to have a timer on it (5 minutes?   might be adjustable), so if you have a script that will take a long time to complete, you might test it here with a subset of data, and then move it to a scheduled job for the big run.



find_real_file.png


payerle
Tera Contributor

Super helpful, I appreciate the feedback there.   I like background scripts, but hate that you can't save them!       Thanks for the heads up about Steve.   I went to K15 and 16, not sure if we are going this year or not, but will keep my ear to the ground on that.   I'll let you know if I come up with anything nifty for my project too.


sabell2012
Mega Sage

Thomas, thanks for the mention!



Matthew:   The article on Fix Scripts you will probably be interested in reading is here:ServiceNow Scripting 101: Two Methods for Code Development



After you have read that; this is a useful upgrade: Mini-Lab: Fix Script Application Enhancement



Steven.


Community Code Snippets: Articles List to Date


payerle
Tera Contributor

Hi Everyone, so I believe I figured this out.   I just moved it into our Prod instance and it seems to be working well.  



To solve this, I added two scripts to the Transform Map.



onBefore:


//This script marks everything that comes in as installed, and then updates the record.   Important for the next step.


var name = source.u_system_name.toString();


if(name.length == 0 ){


  ignore = true;


} else {


  target.install_status = 1;


      target.update();


}


The bold part above is what is important, I had an issue where this was causing the action to create null records and doubling my number of computers, quite annoying.   I fix this in the onComplete script.



onComplete:


//This finds all records that weren't updated 'recently' - could be anything after 10 minutes or later if you want, then marks them as 'retired', and updates those.


var gr = new GlideRecord("cmdb_ci_computer");


gr.addQuery("install_status", "1");


gr.addQuery('sys_class_name','cmdb_ci_computer');


gr.addQuery('sys_updated_on','<=','javascript:gs.hoursAgo(2)');


gr.query();


while (gr.next()) {


      gr.install_status = 7;


  gr.update();


}



//This does my clean up and finds my null values and deletes.   Not terribly clean, but gets the job done.


var gr = new GlideRecord("cmdb_ci_computer");


gr.addQuery('sys_class_name','cmdb_ci_computer');


gr.addQuery("name", "");


gr.query();


while (gr.next()) {


    gr.deleteRecord();


}





All of this runs at 1am EST, and is done within about 10 minutes, so not a lot of stress on the system or any down time.   The coolest part is, if a computer shows up on the first run, then it marks it as installed.   If the same computer is missing from the report on the next day, it retires it.   If the computer checks back into KACE and is active again, and therefore would show up on the report the 3rd day, it marks it as installed again.



So far everything is working well with the inbound action and this transform map.   Thanks for everyone who offered advice and hope this helps others!


Danny Jezerinac
ServiceNow Employee

Do you have the contents of this script?     It does not seem to be attached to the article.     Thanks