Skip to Content
Author's profile photo Tribhuwan Pant

SAPUI5 Integration with Outlook REST APIs

Reference: https://docs.microsoft.com/en-us/outlook/rest/javascript-tutorial

The purpose of this guide is to walk through the process of creating a simple single-page SAPUI5 app that retrieves messages from Office 365 or Outlook.com. The source code in this repository is what you should end up with if you follow the steps outlined here.

We will use the Microsoft Graph to access Outlook mail. Microsoft recommends using the Microsoft Graph to access Outlook mail, calendar, and contacts. You should use the Outlook APIs directly (via https://outlook.office.com/api) only if you require a feature that is not available on the Graph endpoints.

Create the app

Create an empty directory where you want to create your app. For the purposes of this guide I will assume the name of the directory is sapui5-outlook-app, but feel free to use any name you like.

Since our app will be client-side JavaScript-based, we need an HTTP server to serve our HTML and JavaScript files. Feel free to use your favorite HTTP server for this guide. To make things simple, this guide will include steps to use http-server to quickly create a development web server on the command line.

Setup the web server

Before you begin you’ll need to have Node.js installed.

  1. Open a command prompt and set the current directory to the sapui5-outlook-app directory.
  2. Enter the following command to install http-server:
    npm install http-server -g
    
  3. Enter the following command to start the server:
    http-server
    
  4. Open a browser and browse to http://localhost:8080. If the server is working correctly, you should see something like the following:Browser showing a directory listing of an empty directory.

This confirms that the server is working, so we’re ready to start coding. You can leave the server running. If you do stop it at some point, be sure to restart it using the http-server command in the sapui5-outlook-app directory.

Register the app

Head over to the Application Registration Portal to quickly get an application ID.

  1. Using the Sign in link, sign in with either your Microsoft account (Outlook.com), or your work or school account (Office 365).
  2. Click the Add an app button. Enter sapui5-outlook-app for the name and click Create application.
  3. Locate the Platforms section, and click Add Platform. Choose Web, then enter http://localhost:8080 under Redirect URIs. Make sure that there is a check next to ALlow Implicit Flow.
  4. Click Save to complete the registration. Copy the Application Id and save it. We’ll need it soon.

Thus you will have an application id and redirect url which we’ll use in our index.html file to redirect to outlook login page for this app.

Designing the app

Our app will be very simple. When a user visits the site, they will see a link to log in and view their email. Clicking that link will take them to the Azure login page where they can login with their Office 365 or Outlook.com account and grant access to our app. Finally, they will be redirected back to our app, which will display a list of the most recent email in the user’s inbox.

Let’s begin by adding an HTML page to our app. Using your favorite editor, create a file named index.html in the sapui5-outlook-app directory, and add the code in this repository.

Description

Here is the description of important code extracts-

Implementing OAuth2

Our goal in this section is to make the link on our home page initiate the OAuth2 Implicit Grant flow with Azure AD. This flow is designed for SPA apps, and will allow us to get an access token without needing to exchange a client secret or do extra requests to a token issuing endpoint.

The implicit flow is pretty simple. The user browses to an authentication link hosted by Azure, where they sign in and grant access to our app. Azure redirects back to the app with the result. Assuming the user successfully signed in and granted consent, the result contains an access token and ID token.

Our first step is to generate the authentication link.

// App configuration
var authEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?';
var redirectUri = 'http://localhost:8080';
var appId = 'YOUR APP ID HERE';
var scopes = 'openid profile User.Read Mail.Read';

Replace the YOUR APP ID HERE value with the application ID you generated as part of the app registration process.

The buildAuthUrl function

        function buildAuthUrl() {
          // Generate random values for state and nonce
          sessionStorage.authState = guid();
          sessionStorage.authNonce = guid();
          var authParams = {
            response_type: 'id_token token',
            client_id: appId,
            redirect_uri: redirectUri,
            scope: scopes,
            state: sessionStorage.authState,
            nonce: sessionStorage.authNonce,
            response_mode: 'fragment'
          };
          url = authEndpoint + $.param(authParams);
          window.location.href = url;
        }

The guid function

        function guid() {
          var buf = new Uint16Array(8);
          cryptObj.getRandomValues(buf);
          function s4(num) {
            var ret = num.toString(16);
            while (ret.length < 4) {
              ret = '0' + ret;
            }
            return ret;
          }
          return s4(buf[0]) + s4(buf[1]) + '-' + s4(buf[2]) + '-' + s4(buf[3]) + '-' +
            s4(buf[4]) + '-' + s4(buf[5]) + s4(buf[6]) + s4(buf[7]);
        }

Now update the renderWelcome function to call the buildAuthUrl function and set the href attribute of the sign in button to the result. We are creating a demo view of tokens in renderWelcome when login is successful.

        function renderWelcome(isAuthed) {
          if (isAuthed) {
	        var app = new sap.m.App();
	        var oPage = new sap.m.Page({
	          title: "Outlook Integration With SAPUI5",
	          content: [
	            new sap.m.MessageToast.show("Successfully Logged In!", {
	              duration: 1000,                 
	              my: "center center",            
	              at: "center center",             
	            }),
	            new sap.m.VBox({
	              items:[
	                new sap.m.MessageStrip({
	                  text: "Access Token",
	                  type: "Information"
	                }),
	                new sap.m.TextArea({
	                  value: myAccessToken,
	                  growing: true,
	                  width: "100%",
	                  editable: false
	                }),
	                new sap.m.MessageStrip({
	                  text: "ID Token",
	                  type: "Information"
	                }),
	                new sap.m.TextArea({
	                  value: myTokenID,
	                  growing: true,
	                  width: "100%",
	                  editable: false
	                }),
	                new sap.m.MessageStrip({
	                  text: tokenExpire,
	                  type: "Warning"
	                })
	              ]
	            })
	          ],
	          headerContent:[
	            new sap.m.Button({
	              text: "My Inbox",
	              type: "Accept",
	              press: function(){
	                var emailAddress = "YOUR MAIL ID"; 
	                //hardcoding it if you want code to get current user's email please refer to outlook page reference 
	                getUserInboxMessages(emailAddress);
	                function getAccessToken(callback) {
	                  var now = new Date().getTime();
	                  var isExpired = now > parseInt(sessionStorage.tokenExpires);
	                  // Do we have a token already?
	                  if (sessionStorage.accessToken && !isExpired) {
	                    // Just return what we have
	                    if (callback) {
	                      callback(sessionStorage.accessToken);
	                    }
	                  }
	                  else {
	                    console.log("Token Expired! Re-login required!");
	                  }
	                }
	                // function getUserEmailAddress(callback)
	                function getUserInboxMessages(emailAddress, callback) {
	                  getAccessToken(function(accessToken) {
	                    if (accessToken) {
	                      // Create a Graph client
	                      var client = MicrosoftGraph.Client.init({
	                        authProvider: (done) => {
	                          // Just return the token
	                          done(null, accessToken);
	                        }
	                      });
	                      // Get the 10 newest messages
	                      client
	                        .api('/me/mailfolders/inbox/messages')
	                        .header('X-AnchorMailbox', emailAddress)
	                        .top(10)
	                        .select('subject,from,receivedDateTime,bodyPreview')
	                        .orderby('receivedDateTime DESC')
	                        .get((err, res) => {
	                        if (err) {
	                          callback(null, err);
	                        }
	                        else {
	                          var oList = new sap.m.List({
	                          	
	                          });
	                          var oMail =  new sap.m.CustomListItem({
	                            content:[
	                              new sap.m.HBox({
	                                items:[
	                                  new sap.m.CheckBox({
	                                  }),
	                                  new sap.m.VBox({
	                                    items:[
	                                      new sap.m.Label({
	                                        text: "{from/emailAddress/name}",
	                                        width: "100%"
	                                      }).addStyleClass("profileName"),
	                                      new sap.m.Label({
	                                        text: "{receivedDateTime}"
	                                      }).addStyleClass("designation")
	                                    ]
	                                  }),
	                                  new sap.m.HBox({
	                                    items:[
	                                      new sap.m.VBox({
	                                        items:[
	                                          new sap.m.Label({
	                                            text: "{subject}",
	                                            design: "Bold",
	                                            width: "40%"
	                                          }).addStyleClass("subjectLabel"),
	                                          new sap.m.Label({
	                                            text: "{bodyPreview}",
	                                            width: "40%"
	                                          }).addStyleClass("shortText")
	                                        ]
	                                      })
	                                    ]
	                                  })
	                                ]
	                              })
	                            ]
	                          });
	                          var oJSONDataModel;
	                          oJSONDataModel= new sap.ui.model.json.JSONModel();
	                          oJSONDataModel.setData(res.value);
	                          oList.setModel(oJSONDataModel);
	                          oList.bindItems('/',oMail);
	                          var oInboxPage = new sap.m.Page({
	                            title: "Outlook Integration With SAPUI5",
	                            content:[
	                              oList				
	                            ]
	                          });
	                          app.addPage(oInboxPage);
	                          app.to(oInboxPage);
	                        }
	                      });
	                    }
	                    else {
	                      var error = {
	                        responseText: 'Could not retrieve access token' };
	                      callback(null, error);
	                    }
	                  });
	                }
	              }
	            }),
	            new sap.m.Button({
	              icon: "sap-icon://log",
	              type: "Reject"
	            })
	          ]
	        });
	        app.addPage(oPage);
	        app.placeAt("content");   
          }
          else {
            buildAuthUrl();
          }
        }

The handleTokenResponse function

        function handleTokenResponse(hash) {
          // clear tokens
          sessionStorage.removeItem('accessToken');
          sessionStorage.removeItem('idToken');
          var tokenresponse = parseHashParams(hash);
          // Check that state is what we sent in sign in request
          if (tokenresponse.state != sessionStorage.authState) {
            sessionStorage.removeItem('authState');
            sessionStorage.removeItem('authNonce');
            // Report error
            window.location.hash = '#error=Invalid+state&error_description=The+state+in+the+authorization+response+did+not+match+the+expected+value.+Please+try+signing+in+again.';
            return;
          }
          sessionStorage.authState = '';
          sessionStorage.accessToken = tokenresponse.access_token;
          // Get the number of seconds the token is valid for,
          // Subract 5 minutes (300 sec) to account for differences in clock settings
          // Convert to milliseconds
          var expiresin = (parseInt(tokenresponse.expires_in) - 300) * 1000;
          var now = new Date();
          var expireDate = new Date(now.getTime() + expiresin);
          sessionStorage.tokenExpires = expireDate.getTime();
          sessionStorage.idToken = tokenresponse.id_token;
          // Redirect to home page
          window.location.href = redirectUri;
        }

This function clears any cached tokens, then parses the token response. It checks that the state parameter matches what we originally sent, calculates the expiration time for the token, then saves the tokens in the session. Before we test this code, we need to implement the parseHashParams function. Add this function after the guid function.

The parseHashParams function

        function parseHashParams(hash) {
          var params = hash.slice(1).split('&');
          var paramarray = {
          };
          params.forEach(function(param) {
            param = param.split('=');
            paramarray[param[0]] = param[1];
          });
          return paramarray;
        }

Using the Mail API

Now that we can get an access token, we’re in a good position to do something with the Mail API. Let’s start by downloading the Microsoft Graph JavaScript Client Library. We already added a reference to it in the HTML, so all we need to do is download it. Go to https://github.com/microsoftgraph/msgraph-sdk-javascript and download the source. Copy the graph-js-sdk-web.js into the sapui5-outlook-app directory.

The getAccessToken function

	                function getAccessToken(callback) {
	                  var now = new Date().getTime();
	                  var isExpired = now > parseInt(sessionStorage.tokenExpires);
	                  // Do we have a token already?
	                  if (sessionStorage.accessToken && !isExpired) {
	                    // Just return what we have
	                    if (callback) {
	                      callback(sessionStorage.accessToken);
	                    }
	                  }
	                  else {
	                    console.log("Token Expired! Re-login required!");
	                  }
	                }

We’ll use this method anytime we need to use the access token. The function checks if the token is about to expire. If it isn’t, then it just returns the token from the session. If it is, then it refreshes the token.

The getUserInboxMessages function

	                function getUserInboxMessages(emailAddress, callback) {
	                  getAccessToken(function(accessToken) {
	                    if (accessToken) {
	                      // Create a Graph client
	                      var client = MicrosoftGraph.Client.init({
	                        authProvider: (done) => {
	                          // Just return the token
	                          done(null, accessToken);
	                        }
	                      });
	                      // Get the 10 newest messages
	                      client
	                        .api('/me/mailfolders/inbox/messages')
	                        .header('X-AnchorMailbox', emailAddress)
	                        .top(10)
	                        .select('subject,from,receivedDateTime,bodyPreview')
	                        .orderby('receivedDateTime DESC')
	                        .get((err, res) => {
	                        if (err) {
	                          callback(null, err);
	                        }
	                        else {
	                          var oList = new sap.m.List({
	                          	
	                          });
	                          var oMail =  new sap.m.CustomListItem({
	                            content:[
	                              new sap.m.HBox({
	                                items:[
	                                  new sap.m.CheckBox({
	                                  }),
	                                  new sap.m.VBox({
	                                    items:[
	                                      new sap.m.Label({
	                                        text: "{from/emailAddress/name}",
	                                        width: "100%"
	                                      }).addStyleClass("profileName"),
	                                      new sap.m.Label({
	                                        text: "{receivedDateTime}"
	                                      }).addStyleClass("designation")
	                                    ]
	                                  }),
	                                  new sap.m.HBox({
	                                    items:[
	                                      new sap.m.VBox({
	                                        items:[
	                                          new sap.m.Label({
	                                            text: "{subject}",
	                                            design: "Bold",
	                                            width: "40%"
	                                          }).addStyleClass("subjectLabel"),
	                                          new sap.m.Label({
	                                            text: "{bodyPreview}",
	                                            width: "40%"
	                                          }).addStyleClass("shortText")
	                                        ]
	                                      })
	                                    ]
	                                  })
	                                ]
	                              })
	                            ]
	                          });
	                          var oJSONDataModel;
	                          oJSONDataModel= new sap.ui.model.json.JSONModel();
	                          oJSONDataModel.setData(res.value);
	                          oList.setModel(oJSONDataModel);
	                          oList.bindItems('/',oMail);
	                          var oInboxPage = new sap.m.Page({
	                            title: "Outlook Integration With SAPUI5",
	                            content:[
	                              oList				
	                            ]
	                          });
	                          app.addPage(oInboxPage);
	                          app.to(oInboxPage);
	                        }
	                      });
	                    }
	                    else {
	                      var error = {
	                        responseText: 'Could not retrieve access token' };
	                      callback(null, error);
	                    }
	                  });
	                }
	              }
	            }),
	            new sap.m.Button({
	              icon: "sap-icon://log",
	              type: "Reject"
	            })
	          ]
	        });
	        app.addPage(oPage);
	        app.placeAt("content");   
          }
          else {
            buildAuthUrl();
          }
        }

This uses the Graph client that we used in getUserEmailAddress, but this time the call is a little more complicated. It uses query parameters to control the results we get back.

  • Using the top method limits the results to the first 10 messages.
  • Using the select method controls which fields are returned for each message. In this case we only request the subject, from, receivedDateTime, and bodyPreview fields.
  • Using the orderby method sorts the results by the receivedDateTime field in descending order (newest first).

After receiving the response it is further used for data binding in our SAPUI5 mailbox template.

oJSONDataModel.setData(res.value);

Reference: https://docs.microsoft.com/en-us/outlook/rest/javascript-tutorial

Code Repository: https://github.com/3bhu1/3bhu1.github.io/

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.