Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
dianamatache
Explorer
Introduction

This is a submission of the Enhance your bot building with templates blog post series.

In this post I will show you how to automate a process in which you have to search for keywords in Outlook emails. The emails that fit the criteria will be then collected so they can be used for other activities.

What you will learn in this tutorial:

  • How to use the Outlook Library;

  • How to search for a keyword in your emails;

  • How to use wildcards in your search;

  • How to display some details about the emails in the console;


Steps to follow:

1.Create a new workflow;

2.Import Outlook Library Scripts;

3.Add activities in your workflow;

4.Enrich the generated code by your workflow with your custom logic;

Prerequisites:

Microsoft Outlook

Desktop Studio 1.0.8.36

Instructions:

1.Create a new workflow

Create a new project and give it a name.

Go to ‘Workflow’ perspective and create a new workflow.

2.Import Outlook Library Scripts

In the workspace of your new workflow you can use different functions for accessing and manipulating Microsoft Outlook files. In order for your project to compile and run without errors, you first have to enable the Outlook Library scripts in your project:

  • go to “Scripts” perspective;

  • select “Project” tab(bottom-left corner);

  • right click anywhere in the Panel;

  • select “Include library Script”: The “Add Library Script” window pops;

  • enable “Outlook integration”;

  • click on “Save”;



3.Add activities in your workflow

The first activity that you need to add in your workflow is a Custom activity so you can use the functions in the Outlook library. You can give a name and a description for this activity, so you can distinguish better its purpose. I will name mine “SearchKeyWord”. I used the same name for its corresponding step. Using suggestive names will also allow you to better organize your code.

The second activity you should include is an End scenario which indicates that your scenario has ended.

Your workflow should now look like this:


Important: Before you can continue with the rest of the functionalities, you need to build your project. This way the script for the workflow will be generated and we can enhance it.

4.Enrich the generated code by your workflow with your custom logic

After you have built your project, you can proceed to the Scripts perspective and open the script generated by your workflow ( it will have the same name ). Search for your custom activity and step by their name ( here is where the suggestive name comes in handy). You can write the rest of the logic in this step. For this example, I’m searching for emails containing the word “test” anywhere in their body, using wildcards. The function I created contains (in comments) all the possible parameters you can use to search for an email. Please keep in mind that the search is performed in the Outlook accounts you are currently logged in.


Below you can find my code for this step and my comments for each step:
// ----------------------------------------------------------------
// Step: SearchKeyWord
// ----------------------------------------------------------------
GLOBAL.step({
SearchKeyWord: function(ev, sc, st) {
var rootData = sc.data;
ctx.workflow('searchKeyWord', '31e9eec8-fe99-4262-8db7-279548fff558');

// Initializes “Microsoft Outlook” application.
ctx.outlook.init();

var mails = [];
var i;

// Resets the working mails list.
ctx.outlook.mail.resetMailCollection();

// Search the body of email for a keyword. Other criteria are also available.
ctx.outlook.mail.searchByCriteria({
//fromEmail: "",
//subject: "",
//sender: "",
textDescription: "%test%",
//read: 0,
//hasAttachment: 0,
//date: {after : new Date("MM/JJ/AAAA"),before : new Date("MM/JJ/AAAA")},
//maxRow: 10
dontThrowExceptionIfNoMailFound: true
});

// Get the list of mail information for the mails that fit the criteria.
mails = ctx.outlook.mail.getFilteredTable();

// Build the working mails list by retrieving each mail
if (mails.length) {
for (i = 0; i < mails.length; i++) {
ctx.outlook.mail.retrieveMail({
EntryID: mails[i]['EntryID'],
StoreID: mails[i]['StoreID']
});
}

// Display some info about each email.
ctx.log("---------------------------------------------------------");
for (i = 0; i < ctx.outlook.mail.getCollectionLength(); i++) {
ctx.log("Mail no: " + i);
ctx.log("Date: " + mails[i]['Date']);
ctx.log("From: " + mails[i]['Sender']);
ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
ctx.log("---------------------------------------------------------");

}
}

// Ends “Microsoft Outlook” application.
ctx.outlook.end();

sc.endStep(); // end Scenario
return;
}
});

Conclusion

This blog post should help you to understand the use of the ‘Outlook Library’ and how to search for emails using different criteria. At the end, you should be able to understand these functionalities and use them in your scenarios.
19 Comments
Vijay
Active Contributor
dianamatache

Thanks Diana for sharing!!

I have a question, how can i fetch some data from the email body? lets say my email body includes a table


















EmpID Name  Asset No 
xyz ABC 123
uvw ijk 456

Regards

Vijay
dianamatache
Explorer
0 Kudos

Hi Vijay,

You can fetch the content of an email body using the following syntax:

res = ctx.outlook.mail.getBody( 0 );

, where ‘0’ is the mail index from the working mail collection.

This method however will return a string value. For example, I have received the following email that contains your table:

 

 

 

 

I have used the bot I created in this post: SAP Intelligent RPA: Search for e-mails with different criteria  to search for the email above and the email content is displayed like this:

As you see, the text in the table is structured row by row.

Kind regards,

Diana

Vijay
Active Contributor
0 Kudos
dianamatache

Thanks Diana for response.

Yeah, we will get the email body as string. My question was specifically if we could extract the required  key value pairs from that string. Is there any way?

I don't find the available string functions also much useful for this.

Regards

Vijay
0 Kudos
Hi dianamatache,

 

I followed your blog (apart from popup scenario as my requirement is simply to read email from inbox) but facing timeout issue while executing the script. Please find below code snippet

 

ctx.outlook.init();

var mails = []; // will contain mail information
var i; // contor
var dataset = []; // array of arrays in which we insert the mail information

// Resets the working mails list.
ctx.outlook.mail.resetMailCollection();

// Build the search function
try {
ctx.outlook.mail.search({
filter : "urn:schemas:httpmail:subject like 'SAP iRPA - Trigger Email'" + " AND " +
"urn:schemas:httpmail:read=1",
maxRow : 5,
storeName : 'xxx@xxx.com', (My email id from which mail is to be read)
dontThrowExceptionIfNoMailFound: true
});

// Get the list of mail information for the mails that fit the criteria.
mails = ctx.outlook.mail.getFilteredTable();

// Build the working mails list by retrieving each mail
if(mails.length) {
for(i=0; i<mails.length; i++) {
ctx.outlook.mail.retrieveMail({EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']});
}

// Display some info about each email that fit the criteria.
ctx.log("---------------------------------------------------------");
for(i=0; i<ctx.outlook.mail.getCollectionLength(); i++) {
ctx.log("Mail no: " + i);
ctx.log("From: " + mails[i]['Sender']);
ctx.log("Date: " + mails[i]['Date']);
// Covert the date to a string so it can be loaded into the table.
var date = String(mails[i]['Date']);
ctx.log("Aici"+String(mails[i]['Date']));
ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
ctx.log("---------------------------------------------------------");

// Load the details of the current email into the final array (dataset).
dataset.push([date, mails[i]['Sender'], ctx.outlook.mail.getSubject(i), ctx.outlook.mail.getBody(i)]);
}

// Provide the final array of details as datasource for the table.
//POPUPS.outputTable.finalTable.set(dataset);

// Open the popup to display the table.
//POPUPS.outputTable.open();
}
} catch (err) {
ctx.log("Fail (" + err.description + ").");
return e.error.KO;
}

ctx.outlook.end();
sc.endStep(); // end Scenario
return;

 

Error SS


Can you please help here.

 

Thanks and Regards,

Vinay
dianamatache
Explorer
0 Kudos
Hi Vinay,

 

Search through your code for the following code snippet (you should find it under GLOBAL.scenario):

sc.onTimeout(30000, function(sc, st) { sc.endScenario(); }); // Default timeout handler for each step.

 

Here either increase the time, either comment the whole line of code. The search through the email might take a while and probably this is why you get the timeout.

Let me know if it works

 

Kind regards,

Diana
0 Kudos
Hi dianamatache ,

 

I increased the time period to 100000 but still the execution is running into error. When debugging the code it goes to catch section when ctx.outlook.mail.search is executed and the catch section does not give the error description. Please find below code snippets along with debugger screenshot.

Timeout setting

InboxVinayJoshiG.scenario({ readEmailNew: function(ev, sc) {
var rootData = sc.data;

sc.setMode(e.scenario.mode.clearIfRunning);
sc.setScenarioTimeout(600000); // Default timeout for global scenario.
sc.onError(function(sc, st, ex) { sc.endScenario(); }); // Default error handler.
sc.onTimeout(100000, function(sc, st) { sc.endScenario(); }); // Default timeout handler for each step.
sc.step(InboxVinayJoshiG.steps.SearchEmail_1);
}}, ctx.dataManagers.rootData).setId('f2daf9dc-7d46-4870-b2d3-d1ca0895574f') ;

 

Mail search code

ctx.outlook.mail.search({
filter : "urn:schemas:httpmail:subject like 'SAP iRPA - Trigger Email'" + " AND " +
"urn:schemas:httpmail:read=1",
maxRow : 5,
storeName : 'xxxx@xxxx.com',
dontThrowExceptionIfNoMailFound: true
});

 

Catch section

ctx.log("Fail (" + err.description + ").");
return e.error.KO;

 

Debugger screenshot

dianamatache
Explorer
0 Kudos
Hi Vinay,

The error says "timeout" so the time period you used it's not enough. Try to comment the sc.onTimeout and then run your bot again.

 

Kind regards,

Diana
0 Kudos
Hi dianamatache

 

Same result again. Can it be possible that company security policy doesnot allow bot to read email ? If so is there any way we can find that if this issue is due to policy ?

 

Code Snippet

InboxVinayJoshiG.scenario({ readEmailNew: function(ev, sc) {
var rootData = sc.data;

sc.setMode(e.scenario.mode.clearIfRunning);
sc.setScenarioTimeout(600000); // Default timeout for global scenario.
sc.onError(function(sc, st, ex) { sc.endScenario(); }); // Default error handler.
//sc.onTimeout(100000, function(sc, st) { sc.endScenario(); }); // Default timeout handler for each step.
sc.step(InboxVinayJoshiG.steps.SearchEmail_1);
}}, ctx.dataManagers.rootData).setId('f2daf9dc-7d46-4870-b2d3-d1ca0895574f') ;

 

Debugger Screenshot

0 Kudos
Hi vijay.sharma4

Did u get the response for the above ?

i am also facing the similar issue can you help me on this please.

i am getting the email body but unable to split to fetch the information from the body.

Body of the email looks like ,

Hi,

Customer Name: YYYYY

Order Type: OR

Sales Org : Sales Org. 0001

Division: Medicine

Ship-to-party: FAA6

 

i want to read the values and store it in different variables.

Regards,

Avinash
Vijay
Active Contributor
0 Kudos

Hi avinashy,

No perfect solution yet other then using some OCR capabilities.

Although, if the position of you Variables is  fixed, you can extract the values using substring function

var xyz = ctx.string.subString( mailbody, string start position, string end position);

Thanks

Vijay

0 Kudos

Hi vijay.sharma4

Thanks for your quick response

i tried using sub string but its throwing error.i am attaching the flow.can you just have a look and suggest any other way to split and get the values to store in respective variables .

error after using substring

Output of the body :

Hi,

Customer Name: xxxxxx

Order Type: OR

Sales Org : Sales Org. 0001

Division: Medicine

Ship-to-party: FAA6

 

i want to split it and store it in individual variables.please suggest

Thanks

Vijay
Active Contributor
0 Kudos
you need to enable string utilities library

0 Kudos
Thanks vijay.sharma4 , it worked.

Have another question,i am fetching the values but i want to pass them to the variables created in the context .

Can you help me on this please,because the above fetching the values is completely done using custom code.

Regards,

Avinash
Vijay
Active Contributor
try like this

rootData.<your context variable name> = ctx.string.subString( mailbody, string start position, string end position);
0 Kudos
Hi

Is it possible to send the subject in regular expression. Like if I want to search one word in the subject line.

Kindly help me out in this.

Thanks

Sulagna Chakraborty
dianamatache
Explorer
0 Kudos
Hi,

 

Yes, it's possible, the subject is one of the  parameters in the searchByCriteria method. Have a look at the documentation for all the available options.

 

Kind regards,

Diana
0 Kudos
Yes Diana..

It works.. also i found that this is case insensitive.. Is there a way to check for 2 strings in the subject.. something like this as denoted below.

How to denote "and" or "or" in the below example

var subject = "%"+string1+"%" and "%"+another string+"%"

Thanks

Sulagna Chakraborty

 
dianamatache
Explorer
0 Kudos
For simple use cases try subject: "%string1 string2%". For more complex requirements you could try regex to see if it works for you.
josmer1202_86
Discoverer
0 Kudos
Hello.
How to mark an email as read?