Skip to main content

Building a Microsoft Teams Tab Application that uses the Graph API and Exchange OOF data

Over the years I've created a few different versions of In/Out boards like this that have used Exchange FreeBusy information to present the In/Out status for Users. In this post I am going to look at how you can create the same thing in Microsoft Teams using a Team's tab application that will call some Microsoft Graph endpoints that will first get the members of a particular Team, then there OOF MailTip to determine if they have an AutoResponse set and finally get there userphoto. The end results is a board that looks like this

Team's Tab Applications

Team's tab apps are very simular to the Add in's framework used across other Office365 products that utilize JavaScript and html to provide a consistent approach across desktop and web clients. However because teams is fairly new the underlying client SDK isn't as feature rich or mature as you would find for example with Exchange/Outlook. Some examples of this is there is no way to get the members of a Team using the client SDK (v1.0). Also the Authentication methods to get the token to use against other workloads is not as seamless and in some cases relies on Auth popups that can be blocked by web browsers.

Getting Started

To get started with developing and using your own custom tab applications you first need to enable side loading of Apps in the Office365 Admin portal ref .The important part is "Sideloading is how you add an app to Teams by uploading a zip file directly to a team. Sideloading lets you test an app as it's being developed. It also lets you build an app for internal use only and share it with your team without submitting it to the Teams app catalog in the Office Store. "

You also will need somewhere to host your pages a good free solution is GitHub pages  or Azure if you have a subscription or credits via MSDN etc.

An Application registration is needed which is used in both the Teams manifest and it allows you to assign what rights your Team app will have to other workloads in the Graph API. To Create a app registration see . This sample app uses a v1 registration


Because this app accesses various graph endpoints different oauth Grants need to be allowed eg
Admin Consent 

Once you have your application registration setup with the correct user grants for what you plan to access because some of these permissions may require Administrative Consent you will need to consent to its use within your tenant. The easiest way to do this is in a Web Browser, eg post the following where you replace the Client_Id with the application Id from the registration you just created.  

Installing a Custom tab app

Once you have met all the prerequisites you are now ready to upload the App into teams and enable it on your desired channel. To do this you need to use the "upload a custom app" link which is available when you click ManageTeam-Apps tab see

(Note if you don't see  the "upload a custom app" check that you have side loading of apps enabled in your tenant config)

What you upload here is a Zip file containing your manifest file and two images that you manifest refers to for eg
   "icons": {
    "outline": "Outline32.png",
    "color": "Colour192.png"

For this sample this is located in

These icons are what is used in the UI to represent your application.

How the code works

Because the code uses the Graph API to get the Team Members, AutoResponse Mailtip and Profile picture the first thing it must do is get a Token to use against the Graph endpoint. With this sample it uses the JavaScript ADAL which allows you to do a silent Authentication if a cached token is already available otherwise a popup is used to authenticate the user (in most cases the user doesn't need to enter anything the popup will showup and be able to use the currently logged on creds). The Authentication flow through tab applications is explained in detail here .

Once a Token has been acquired the requests to the Graph are relatively straight forward, for performance reasons the requests are preformed asynchronously so the app can be as responsive to the user as possible.


Because this was proof of concept sample its not optimized for performance, eg for things like getting the user photo if you had a very large group then this could potentially take quite a while to get and render all these images (eg you need to start implementing paging and caching things in blob storage to improve performance and user response).

All the code for this sample is available in GitHub

Its also hosted in GitHub pages if you have a development tenant and want to test it (you will need to first use the admin consent URL listed above).

This is just a sample to show what you can do within the teams client to bring in data from other workloads. Other things you could do with this is provide a reporting interface directly within a Teams channels for the data provided by the Graph endpoint who's functionality is constantly growing.

Hire me - If you would like to do something similar to this or anything else you see on my blog I'm currently available to help with any Office365, Exchange or Active Directory related development work or scripting please contact me at too big or small).

Popular posts from this blog

Downloading a shared file from Onedrive for business using Powershell

I thought I'd quickly share this script I came up with to download a file that was shared using One Drive for Business (which is SharePoint under the covers) with Powershell. The following script takes a OneDrive for business URL which would look like This script is pretty simple it uses the SharePoint CSOM (Client side object Model) which it loads in the first line. It uses the URI object to separate the host and relative URL which the CSOM requires and also the SharePointOnlineCredentials object to handle the Office365 SharePoint online authentication. The following script is a function that take the OneDrive URL, Credentials for Office365 and path you want to download the file to and downloads the file. eg to run the script you would use something like ./spdownload.ps1 '

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is. I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned) #Define Date to Query $StartDate = (Get-Date) $EndDate

The MailboxConcurrency limit and using Batching in the Microsoft Graph API

If your getting an error such as Application is over its MailboxConcurrency limit while using the Microsoft Graph API this post may help you understand why. Background   The Mailbox  concurrency limit when your using the Graph API is 4 as per . This is evaluated for each app ID and mailbox combination so this means you can have different apps running under the same credentials and the poor behavior of one won't cause the other to be throttled. If you compared that to EWS you could have up to 27 concurrent connections but they are shared across all apps on a first come first served basis. Batching Batching in the Graph API is a way of combining multiple requests into a single HTTP request. Batching in the Exchange Mail API's EWS and MAPI has been around for a long time and its common, for email Apps to process large numbers of smaller items for a variety of reasons.  Batching in the Graph is limited to a m
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.