Managing your own O365 Add-Ins moved in the menus…..

As of this week I have been unable to find where I can manage my own add-ins. Within Office 365 you have the ability to install you own, and if your admin gives you the ability you can turn off Add-Ins you don’t want.

The option to do this used to be under the main menu for add-ins….

add1

But it now moved under

My App Settings > Mail > General > Manage Add-Ins

Which is surely more complicated than it was before…….

add2

As is often the case, this is more of a public service to my own forgetfulness as I will need to remember this again I expect….

Unless it gets moved again.

Programatically modifying the subject within an Outlook Email using an Office Add-in

In this article I will demonstrate the simple getter and setter methods for getting the subject from an Outlook email, changing it and updating it.

Introduction

A customer came to us with the request to be able to push a button in outlook and set distinct values into the subject line of an email. The reason for wanting to do it this was way to ensure that there was no spelling issues and or other potential mistakes. The information in the subject can then be parsed and acted on as it passes through the email transport process.

Getting and Setting the subject

Looking at the dev.outlook.com documentation for Add-Ins we can see that there are two Async methods for getting and setting the subject from an email.

   getAsync(options, callback)
   setAsync(subject, options, callback)

in both cases the options variable is able to pass information into the Async function so it can be executed on after at the time the callback is executed. In this case we will not be using them.

To demonstrate the capability I used my Firebug lite console within both the outlook and owa clients to get the subject, add a message to it and then set the subject. This gives the overall impression to the user that you are “inserting” the information into the email subject.

Office.context.mailbox.item.subject.getAsync(
	{},
	function(res){
		var subject = res.value
		Office.context.mailbox.item.subject.setAsync(
			'[RANDOMTEXTHERE] '+subject 
		{},
		function(){
		})
	})

In Outlook

o1

o2

and in OWA

o3

o4

This simple functionality can be added into a button within the Ribbon bar and you have the desired Add-In for the customer.

Conclusion

In this article we have seen that getting and setting the Subject of an email in Outlook/OWA is very simple and easy to run within the client/browser

Using RegEx to extract MIME parts from a Microsoft Graph API email stream

In this article I will demonstrate how a Regular Expression can be used to extract all MIME content references from within an HTML Stream.

Introduction

In the previous article we looked at how the base64 encoded version of an embedded MIME Image can be extracted from the Microsoft Graph. In this article we will start to look at how we are going to  automate the solving of that problem by identifying all the MIME encoded images from within the graph API HTML stream.

Regular expressions

RegEx is mentally challenging to most of us, and that is why some beautiful people created Stackoverflow and Google. I was able to find this solution to a similar problem of extracting tag attributes from an HTML string.

Modifying this slightly for my needs in context of the graph I was able to come up with the following:

var content = data.body.content;
var cids = content.match(/cid["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)?/g);

and this will take an HTML stream with different kinds of MIME reference and return them all as an array.

Here is the sample HTML string with just the images highlightedc1

and here’s the result of the test in firebug logging the cids array

c2

 

Conclusion

In this article we have seen that with a simple Regular expression we can extract the Image src attributes relating to the MIME parts within the MS Graph API feed.

Caveat: This assumes a lot about the structure of the API and that is will continue to conform to this structure.

 

Obtain an Office 365 OAuth token from within an Office Add-in without pop-ups or dialogs

In this article I will describe a simple process for generating and storing an O365 token from within an Office Add-in.

Introduction

In the previous article  I described the github project and sample code for creating and getting an Office 365 OAuth Token for use in an Office Add-in. This was an improvement on the previously accepted method for getting a token which required additional services and knowledge of C#. The biggest issue encountered was that the normal OAuth Token process when you log into Office365 takes you through multiple domains. When this happens in the Office Client Add-ins the user is thrown into a separate Internet Explorer. The generated token can then no longer be passed to the Add-in for programmatic use.

This article described how the issue has been overcome and the release of the new simplified code.

The same approach, but a new approach

As discussed in this article it is possible to access more than one domain within an Add-in by adding the additional domains to the Add-In manifest.

If we follow the OAuth process for Office 365 authorization we can see that there are two domains which are used:

We initially request access from “https://login.windows.net/common/oauth2/authorize? ” and then get redirected to “https://login.microsoftonline.com ” before getting sent back to the original.

To solve the issue at hand we add those two domains to the manifest in the following manner

  <AppDomains>
    <AppDomain>https://login.windows.net</AppDomain>
	<AppDomain>https://login.microsoftonline.com</AppDomain>
  </AppDomains>

In the github repo I have actually posted a complete sample manifest file for you to see.

The code 

d3

The code for the Authorization is relatively simple. The Home.js code is triggered when the page loads. If the location.href of the Add-In contains the access_token then we move to app.returnToken(). if not then we “getToken”.

//Home.js
(function () {
    'use strict';

    // The Office initialize function must be run each time a new page is loaded in the Add-In
    if (location.href.split("access_token").length < 2){
        Office.initialize = function (reason) {
            $(document).ready(function () {
                //check to see if there is an OAuth Token cached in the cookie
                //app.addinName will need to be different for every Add-In
                var token = app.getCookie(app.addinName)
                if (!token) {
                    var tokenParams = {};
                    tokenParams.authServer = 'https://login.windows.net/common/oauth2/authorize?';
                    tokenParams.responseType = 'token';
                    tokenParams.replyUrl = location.href.split("?")[0];

                    //THESE tokenParams need to be changed for your application
                    tokenParams.clientId = 'Your-app-clientId-goes-here';
                    tokenParams.resource = "https://yoursite.sharepoint.com";

                    app.getToken(tokenParams);
                } else {
                    //we have a token therefore carry on
                    app.tokenCallback(token)
                }
            });
        };
    } else {
        //The window has the access_token in the URL
        $(document).ready(function () {
            app.returnToken();
        });
    }
})();

The important parts of the App.js code are the getToken and returnToken. Within getToken(tokenParams) we parse out the incoming object and redirect the user to the login screen part of the process using location.href. The reason for having a Home.js separate from App.js is really for clarify.

//App.js
//...
    app.getToken = function (tokenParams) {

        var url =   tokenParams.authServer +
                    "response_type=" + encodeURI(tokenParams.responseType) + "&" +
                    "client_id=" + encodeURI(tokenParams.clientId) + "&" +
                    "resource=" + encodeURI(tokenParams.resource) + "&" +
                    "redirect_uri=" + encodeURI(tokenParams.replyUrl);

       // var winObj = window.open(url);
       // winObj.focus();
        location.href=url;
    };
//...

Putting this all together, when accessing the Add-in for the first time, the user now sees the login screens within the Add-in


o1

o2

And then once logged in the user is sent back to the original screen but with the Authorization token appended to the URL

o3

The returnToken() part of the application parses the incoming URL, extracts the Token and then inserts it into the page for display. The token is then stored in a cookie for 1 hour. This is the length of time the Authentication token is valid. The next time the user opens the Add-in within the hour the token will be stored and accessible.

//App.js
//...
app.returnToken = function(){
        var urlParameterExtraction = new (function () {
            function splitQueryString(queryStringFormattedString) {
                var split = queryStringFormattedString.split('&');

                // If there are no parameters in URL, do nothing.
                if (split == "") {
                    return {};
                }

                var results = {};

                // If there are parameters in URL, extract key/value pairs.
                for (var i = 0; i < split.length; ++i) {
                    var p = split[i].split('=', 2);
                    if (p.length == 1)
                        results[p[0]] = "";
                    else
                        results[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
                }
                return results;
            }

            // Split the query string (after removing preceding '#').
            this.queryStringParameters = splitQueryString(window.location.hash.substr(1));
        })();

        var token = urlParameterExtraction.queryStringParameters['access_token'];

        if (token){
            app.tokenCallback(token)
        } else {
            document.write("Shame")
        }
        /*if (window.opener){
            window.opener.app.tokenCallback(token);
            window.close()
        } else {
            document.write("There appears to have been an error, please close the window and check with your administrator")
        }*/

    }

	app.tokenCallback = function(token){
		//this would then continue to do what you really need in the Add-In
        document.getElementById('tokenHere').innerHTML = token
	}
//...

Sample code only

The code displayed in this example is for example only. It is there to demonstrate the process and return the token. What you then do with the token is up to you 🙂

Conclusion

In this article we have seen how we can create an Office 365 OAuth token with the minimum of impact on the user. They have to log into the Add-in within the Outlook client and the disruption on the User Experience is minimal.

 

Using more than one domain inside of an Office Add-In

In this article I am going to introduce the  <AppDomains> parameter within an Office Add-In Manifest. Using this parameter we are going to see how you can change the URL within an Add-In and consider the possibilities that brings us.

Introduction

I was casually reading through the thrilling “Office Add-ins XML Manifest” (http://dev.office.com/docs/add-ins/overview/add-in-manifests) and I came across this casual comment:

By default, if your add-in tries to go to a URL in a domain other than the domain that hosts the start page (as specified in the SourceLocation element of the manifest file), that URL will open in a new browser window outside the add-in pane of the Office host application. This default behavior protects the user against unexpected page navigation within the add-in pane from embedded iframe elements.

To override this behavior, specify each domain you want to open in the add-in window in the list of domains specified in the AppDomainselement of the manifest file. If the add-in tries to go to a URL in a domain that isn’t in the list, that URL will open in a new browser window (outside the add-in pane).”

This was the exact problem I had when I came up with the O365Token solution on how to Authenticate an Add-in to O365 and ended up using a window.open() solution. When I tried to do the OAuth redirect it failed because it opened a whole new Internet Explorer instance which did not communicate with the Add-in parent.

The published solution works but is a somewhat poor user experience due to the Internet Explorer window opening up. But hey it worked so I went with it.

The problem demonstrated
I am demonstrating this issue using firebuglite in one of my existing Add-ins. I change the location.href of the Add-in (in Outlook) and the requested website opens up in a fresh Internet Explorer window.

d1

d2

Proof of concept

I created a simple addition to my manifest file:

  <AppDomains>
    <AppDomain>https://login.windows.net</AppDomain>
	<AppDomain>https://login.microsoftonline.com</AppDomain>
  </AppDomains>

I uploaded the new file through the Exchange admin portal, refreshed it for the user and tested it again

d3

d4

and look at that – it opened within the Add-in without issue.

Conclusion

In this article I have demonstrated how using the  <AppDomains> parameter within the manifest file we are able to change the website loaded within the Add-in

Next – how do we re-write the O365Token to load nicely in this window?

How to create Dynamic Workflow functionality in Outlook Add-Ins based on unique keys

In this article I will demonstrate how to use a regular expression to provide dynamic contexual assignment of an Outlook add-in. Using that regular expression we will be able to identify the necessary information to link the Add-In to some external dynamic workflow functionality.

Introduction

During the Collab365 presentation I demonstrated a workflow application which was a simple vacation request approval. In that demonstration I showed how we are able to detect a unique key inside of an email and then use that value to open the workflow within the add in (https://youtu.be/t6kRFV09TYs?t=1950).

In previous articles I have demonstrated how to create a contextual add-in and in this article we will look at how we can take that up a notch and make the context dynamic and useful.

I am going to demonstrate the capability in the context of a napacloud add-in so that you are able to work along.

Messing with RegEx

Regular Expressions are a weird an wonderfully powerful capability, generally reserved for people way smarter than me to figure out. Fortunately there are many example sites which can be used to help you figure out how you should build your regular expression.

I used http://scriptular.com/ which allowed me to test my regular expression until I made it work.

We need to create a unique key within out email so that it can be picked up by Outlook. We cannot use an existing URL though because there is already functionality associated with that.

r2

Using regular expressions in an Office Add-in

Inside of the napacloud tooling we are able to play with adding a regular expression to the context of the Add-In.

r1

So I insert my regular expression into the box, save and run. In this case (for demonstration I make the number of characters fixed to be 6)

r3

Test Email

I created a simple test email with a few expressions which COULD match……and when the Add-In runs – only only of the links is highlighted

r4

So now what?

Well what we want to happen is when the user clock on that Workflow Id: Ac9sXP link we want to take them to the right page within our Application (surfaced through the Add-In).

Within the Office.initialize we are able to determine functionality which happens when the user selects the Add-In. I used the same regular expression to match the desired Workflow Id

Office.initialize = function (reason) {
        $(document).ready(function () {
            Office.context.mailbox.item.body.getAsync(
		  "text",
		  { asyncContext:"This is passed to the callback" },
		  function callback(result) {
		    // Do something with the result
			var str = result.value; 
			var res = str.match(/Workflow\sId:\s[0-9|a-z|A-Z]{6}/g).toString();      				
			$("#content-main").html("The RegEx matched is---> "+res)
		  });
        });
    };

When you run the sample in the browser you get this

r5

More advanced

Once you have this string in JavaScript you can do a number of things with it, the two most obvious to me are:

  • Create an iFrame within the application and add the WorkflowID to the Query String
  • If you have an angular application you can then route the user to the correct document using the WorkflowID

Conclusion

In this article I showed how to create a contextual addin using a semi-complex Regular Expression. Then using that exposed value from the email we can surface dynamic functionality for the user.

The Code

I have posted the code from this sample napacloud out on GitHub for anyone who wants to download it an play with it

You can find it here:

https://github.com/markyroden/RegExInOutlookAddIn

 

“Office 365 Add-Ins – a web developer’s playground” – presentation from Collab365 conference now live

Last week I presented at my first non-IBM conference and it was a total blast. At PSC, we see a number of customers who are doing mail migrations who still need to integrate their remaining business critical systems with Office 365. Office Add-Ins, especially in the context of mail and workflow are a great way to look at this integration problem.

The collab365 conference required me to prerecord the presentation and it was streamed at the agenda time. This allowed me to sit in the side chat and talk to the people watching the presentation. This increased interaction and with hindsight I should have worked it more.

This recording is similar to the presentation I gave at ICONUS and Engage.ug this year, but not specifically focused on XPages/Domino integration. The XPages/Domino examples are all in here though and also an example of integration with Watson Tone analysis.

All the presentation from the Collab365 conference are now available and can be accessed here – you will need to create a free registration to get at them all.

https://collab365.conferencehosts.com/confs/Summit2016

Hope you enjoy, there is a lot to learn and a lot of interesting possibilities with the new Office Add-In model.