Skip to Content
Technical Articles
Author's profile photo Rosa ORIHUELA

SAP Intelligent RPA: Exploring the Outlook Library

SAP Intelligent Robotic Process Automation (SAP Intelligent RPA) is a  three-component product that allows users to build and direct process execution bots in various modes to automate business processes.

To build bots, we use different extensions, one of those is the Microsoft Outlook Extension

This library is a collection of functions for accessing and manipulating Microsoft Outlook files. The global variables and functions are used to handle the Outlook instance: start, maintain and stop the Outlook engine. The mail functions are used to manipulate mails in the outlook application.

Some technical points:

  • A mail collection contains mails that have been created and/or created.
  • Search in outlook folder uses an intermediate filter table allowing faster filtering.
  • Retrieving a mail is based on EntryID and optionally storeID.

To get the most of this library, here are a few code examples that will increase in complexity from sending a simple email to encoding an image and then attached it to an email.

First make sure you have the Outlook Library. To check, go to Libraries and check Outlook Integration library.


Let’s review how to send basic emails, we use ctx.outlook.mail.send to do so.  Below the example code:

function sendBasicMail() {
// Initializes “Microsoft Outlook” application.
  ctx.outlook.init();
// Creates a basic mail.
  ctx.outlook.mail.create({To:'name@company.com', Subject:'Test mail from SAP', Body:'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'});
  try {
// Sends the mail.
    var res = ctx.outlook.mail.send(0);  
  } catch (err) {
  ctx.log("Sending of “Microsoft Outlook” mail in failure (" + err.description + ").");
  return e.error.KO;
  }
// Ends “Microsoft Outlook” application.
  ctx.outlook.end();
}

To send emails using another account, you need to use the sendUsingAccount method where you add the email that you want to send from:

function sendMailFromAnotherStore() {
	ctx.outlook.init();
	ctx.outlook.mail.create( {
		To:'example@sap.com,',
		Subject:'[OUTLOOK LIBRARY TEST] - from another store',
		Body:'[OUTLOOK LIBRARY TEST] - Body from another store'
	});
	ctx.outlook.mail.sendUsingAccount(0, 'example@sap.eu');
	ctx.outlook.end();
}

 

If you run into the below error, please make sure the email has been written correctly.

 

If you run into the error:

[ctx.outlook.mail.sendUsingAccount] Failed to send mail with specific account. [ctx.outlook.mail.send] The account cannot be identified. The input parameter was…

You can resolve this issue by adding the account you want to send from into you outlook. If you just add the email under the inbox, it fails as described.


 

To move mail in another store, you need to use the resetMailCollection method, see below:

function moveMailInAnotherStore() {
	var mails = [];
	var i = 0;


	ctx.outlook.init();
	ctx.outlook.mail.resetMailCollection();
	ctx.outlook.mail.searchByCriteria( {
		subject : "Documentation - Wiki - Installation guide - Proxy"
	});


	mails = ctx.outlook.mail.getFilteredTable();
	if (mails.length) {

		for (i = 0; i< mails.length; i++) {
			ctx.outlook.mail.retrieveMail( {
				EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']
			});
		}

		ctx.log("---------------------------------------------------------");
		for (i = 0; i< ctx.outlook.mail.getCollectionLength(); i++) {
			ctx.log("Mail n°" + i);
			ctx.log("From: " + mails[i]['Sender']);
			ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
			ctx.log("Importance: " + ctx.outlook.mail.getImportance(i));
			ctx.log("---------------------------------------------------------");
		}
		ctx.outlook.mail.moveToSpecificStore(0, 'example@sap.eu', 'Inbox\\Testu');
	}
	ctx.outlook.end();
}


If you want to search an email by criteria and would like to avoid the exception if there is no email with such criteria. You will use some functions from the ctx.outlook.application. This class contains a set of functions that manipulate mail items in Outlook.

function dontThrowException() {

            var mails = [];
            var i = 0;
            ctx.outlook.init();
            ctx.outlook.mail.resetMailCollection();
            ctx.outlook.mail.searchByCriteria( {

                        subject : "Narf", dontThrowExceptionIfNoMailFound: true

            });

            //

            mails = ctx.outlook.mail.getFilteredTable();
            if (mails.length) {

                        for (i = 0; i< mails.length; i++) {
                                    ctx.outlook.mail.retrieveMail( {
                                               EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']
                                   });
                        }

                        ctx.log("---------------------------------------------------------");

                        for (i = 0; i< ctx.outlook.mail.getCollectionLength(); i++) {

                                   ctx.log("Mail n°" + i);

                                   ctx.log("From: " + mails[i]['Sender']);

                                   ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));

                                   ctx.log("Importance: " + ctx.outlook.mail.getImportance(i));

                                   ctx.log("---------------------------------------------------------");

                        }

                        ctx.outlook.mail.moveToSpecificStore(0, 'example@sap.eu', 'Inbox\\Testu');

            }

            ctx.outlook.end();

}

 

To reply to an email and attached the body of the email you are replying, you need to use ctx.outlook.mail.reply(0), which replies to the indexed mail.

function replyInsertBody() {
	var mails = [];
	var i = 0;


	ctx.outlook.init();
	ctx.outlook.mail.resetMailCollection();
	ctx.outlook.mail.searchByCriteria( {
		subject : "Test appendBody"
	});
	// 

	mails = ctx.outlook.mail.getFilteredTable();
	if (mails.length) {

		for (i = 0; i< mails.length; i++) {
			ctx.outlook.mail.retrieveMail( {
				EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']
			});
		}

		ctx.log("---------------------------------------------------------");
		for (i = 0; i< ctx.outlook.mail.getCollectionLength(); i++) {
			ctx.log("Mail n°" + i);
			ctx.log("From: " + mails[i]['Sender']);
			ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
			ctx.log("Importance: " + ctx.outlook.mail.getImportance(i));
			ctx.log("---------------------------------------------------------");
		}
		ctx.outlook.mail.reply(0);
		var index = ctx.outlook.mail.getCollectionLength() -1;
		ctx.outlook.mail.appendBody(index, "New body");
		ctx.outlook.mail.send(index);
	}
	ctx.outlook.end();
}

If you want to search for emails in another account, you use the ctx.outlook.mail.search method, which searches for mail information with user-defined filter in object parameter. As shown below,  always wrap up this method with a try…catch statement for best practice.

function searchInAnotherAccount() {
	var mails = [];
	var i = 0;

	// Initializes “Microsoft Outlook” application.
	ctx.outlook.init();
	// Resets the working mails list.
	ctx.outlook.mail.resetMailCollection();
	// Sets a filter to retrieve all unread mails (with max set to 10).
	try {
		ctx.outlook.mail.search( {
			filter : "\"" + "urn:schemas:httpmail:read" + "\"" + "= 0",
			maxRow : 10, storeName : 'example@sap.eu'
		});
	} catch (ex) {
		ctx.log("no email found");
		return e.error.KO;
	}
	// Retrieves the result of search.
	mails = ctx.outlook.mail.getFilteredTable();
	if (mails.length) {
		// Build the working mails list by retrieving the detail of each mail.
		for (i = 0; i< mails.length; i++)
			try {
			ctx.outlook.mail.retrieveMail( {
				EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']
			});
		} catch (ex) {
			ctx.log("could not retrieve an email");
		}
		// Displays some information of each mail in debug prints.
		ctx.log("---------------------------------------------------------");
		for (i = 0; i< ctx.outlook.mail.getCollectionLength(); i++) {
			ctx.log("Mail n°" + i);
			ctx.log("From: " + mails[i]['Sender']);
			ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
			ctx.log("Importance: " + ctx.outlook.mail.getImportance(i));
			ctx.log("---------------------------------------------------------");
		}
	}
	// Ends “Microsoft Outlook” application.
	ctx.outlook.end();
}

If you want to search an email in a specific folder, in this example we also use the search method but the parameters are different. We use folderName instead. The search method takes string typed filters used to search for mail.

function searchInFolder() {
	var mails = [];
	var i = 0;

	// Initializes “Microsoft Outlook” application.
	ctx.outlook.init();
	// Resets the working mails list.
	ctx.outlook.mail.resetMailCollection();
	// Sets a filter to retrieve all unread mails (with max set to 10).
	try {
		ctx.outlook.mail.search( {
			filter : "urn:schemas:httpmail:subject like '%remboursement%' AND urn:schemas:httpmail:read = 0 ",
			maxRow : 10, folderName : 'Mutuelle'
		});
	} catch (ex) {
		ctx.log("no email found");
		return e.error.KO;
	}
	// Retrieves the result of search.
	mails = ctx.outlook.mail.getFilteredTable();
	if (mails.length) {
		// Build the working mails list by retrieving the detail of each mail.
		for (i = 0; i< mails.length; i++)
			try {
			ctx.outlook.mail.retrieveMail( {
				EntryID : mails[i]['EntryID'], StoreID : mails[i]['StoreID']
			});
		} catch (ex) {
			ctx.log("could not retrieve an email");
		}
		// Displays some information of each mail in debug prints.
		ctx.log("---------------------------------------------------------");
		for (i = 0; i< ctx.outlook.mail.getCollectionLength(); i++) {
			ctx.log("Mail n°" + i);
			ctx.log("From: " + mails[i]['Sender']);
			ctx.log("Subject: " + ctx.outlook.mail.getSubject(i));
			ctx.log("Importance: " + ctx.outlook.mail.getImportance(i));
			ctx.log("---------------------------------------------------------");
		}
	}
	// Ends “Microsoft Outlook” application.
	ctx.outlook.end();
}

Finally, if you want to send an email with an image in the body. To do so we use var txt = ctx.fso.file.read( file, e.file.encoding.ASCII ) to read the file and e.file.encoding.Binary to encode the image.

function sendMailWithImageInBody() {
	var imagePath = "C:\\ProgramData\\SAP\\Intelligent RPA\\SDK 2.0.2.6\\templates\\resources\\bmp64\\agent128.png";
	
	ctx.outlook.init();
	ctx.outlook.mail.create( {
		To:'example@sap.com', Subject:'Test email with image'
	});
	var body_text = '<!DOCTYPE html>';
	body_text += '<html>';
	body_text += ' <head>';
	body_text += '<title>HTML img Tag</title>';
	body_text += '</head>';
	body_text += '<body>';
	body_text += '<img src="data:image/png;base64,' + ctx.base64.encodeStream(ctx.fso.file.read(imagePath, e.file.encoding.Binary)) + '">';
	body_text += '</body>';
	body_text += '</html>';
	try {
		ctx.outlook.mail.setBodyHtml(0, body_text);
		var res = ctx.outlook.mail.send(0);
	} catch (err) {
		ctx.log("error : " + err);
	}
	ctx.outlook.end();
}

These were some examples on all the things you can do with the outlook library in order to extract and manipulate mails. I hope you find these examples helpful, let me know if I should add other ones.

Assigned Tags

      8 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jawanth Vytheeswaran
      Jawanth Vytheeswaran

      Hi Rose,

      very informative and useful article.

      I had a question on the "search for emails in another account" case.

      How is the authentication handled?

      i.e. when I access outlook from my bot, it defaults to my account (say "abc@sap.com") and does not ask for additional authentication. But if it the bot has to access another Outlook account, such as "example@sap.com", I suppose authentication has to be provided for that account.

      (I do not presently have an additional account to check this out, but wanted to understand how this works)

      Author's profile photo Jerome GRONDIN
      Jerome GRONDIN

      Hi Jawanth Vytheeswaran

       

      Using Outlook, you can add accounts, using the option "Account Settings". There, you might need to provide the password of the account you want to access to.

      Once it is done, the account is automatically loaded in your Outlook, and directly available by your bot. So you don't have to authenticate with your bot, as it was already done once directly in Outlook

       

      J.

      Author's profile photo Ganesh Babu
      Ganesh Babu

      Thanks for the article!

      I have an issue with the following method :

      ctx.outlook.mail.reply(0);
      ctx.outlook.mail.appendBody(index, "New body");

       

      The reply() method is not actually “replying” to the mail. It is just appending the text “New Body” to the existing mail body and sending the same mail again.

      What am I missing here?

       

       

       

       

       

      Author's profile photo Abhijeet Kamble
      Abhijeet Kamble

      Nice Article 🙂

       

      Do you have any idea how to use below function of outlook.

       

      ctx.outlook.mail.move(oIndex, Object);

       

      Can you give an example of it.

       

      Thanks,

      Abhijeet

      Author's profile photo Ankit Maskara
      Ankit Maskara

      Hi Rosa ORIHUELA ,

      Thanks for the blog. I needed advice on below error which I am getting on executing a simple bot which automates sending of email, appreciate any help here.

      Thanks and Regards,

      Ankit Maskara.

      Author's profile photo Ankit Maskara
      Ankit Maskara

      For anyone facing this issue, here is how it was resolved for me - Earlier I tested keeping Outlook closed. Once I opened the outlook and ran the bot it worked.

      Thanks.

      Author's profile photo Steven De Baerdemaeker
      Steven De Baerdemaeker

      Hi

      Great blogpost, it helped me a lot.

      There is however one thing, that fails or seems missing, and that is a possibility to search for emails in “all subfolders”. My customer has a mailbox with multiple subfolders and upon mail arrival, rules are automatically moving emails to the relevant folders (unread).
      Folders can be added/changed/removed and we don't know the names upfront.

      Our bot needs to search for all unread objects irrelevant of the subfolders, but there seems a missing option to specify the scope, in the search method.

      e.g. Outlook.OlSearchScope.olSearchScopeAllFolders

      Is there a workaround for this?

      Without, we are blocked in this development

      Author's profile photo Jose Mera
      Jose Mera

      Hi,

      How to mark an email as read?