Configure Outlook Add in capability within your Teams app - OfficeDev/TeamsFx GitHub Wiki

Configure Outlook Add-in capability within your Teams app

Introduction

Office Add-ins are web apps that extend the functionality of Outlook. Some of the things that can be done with an Outlook Add-in:

  • Read and write the content of email messages and meeting invitations, as well as responses, cancellations, and appointments.
  • Read properties of the user's mailbox.
  • Respond automatically to events, such as the sending of an email.
  • Integrate with external services including CRM and project management.
  • Add custom ribbon buttons or menu items to perform specific tasks.

For more information, start with Outlook Add-ins Overview.

Prerequisites

To configure an Office Add-in as additional capability, you must meet the following conditions:

  • You have a Microsoft 365 account to test the application. For example, an *.onmicrosoft.com account.
  • Your Micrsoft 365 account has been added as an account in desktop Outlook. See Add an email account to Outlook
  • To deploy the Teams app to Azure as described in the last section of this article, you need an Azure account to an Azure subscription. Create your free Azure account if you don't already have one by using the link Free Azure account.

Overview

The following are the major steps to adding an Outlook Add-in to a Teams app. Details are in the sections below.

  1. Prepare the Teams app project
  2. Create an Office Add-in project that is initially separate from your Teams app project.
  3. Merge the manifest from the Outlook Add-in project into the unified Microsoft 365 manifest.
  4. Copy the Outlook Add-in files to the Teams app project.
  5. Edit the tooling configuration files.
  6. Move the application to Azure.

Prepare the Teams app project

Begin by separating the source code for the tab (or bot) into its own subfolder. These instructions assume that the project initially has the following structure. To create a Teams app project with this structure, be sure you are using the prerelease version of Teams Toolkit: v4.99.2023031507 or later.

|-- .vscode/
|-- appPackage/
|-- build\appPackage/
|-- env/
|-- infra/
|-- node_modules/
|-- public/
|-- src/
|-- gitignore
|-- package-lock.json
|-- package.json
|-- teamsapp.local.yml
|-- teamsapp.yml
|-- tsconfig.json

NOTE: If you are working with a new Teams tab project, the \node_modules folder and the package-lock.json file will not be present until you run npm install in the root of the project. The build\appPackage folder will not be present until after the first time you debug the project.

  1. Create a folder under the root named "tab" (or "bot").

    NOTE: For simplicity, the remainder of this article assumes that the existing Teams app is a tab. If you started with a bot instead, replace "tab" with "bot" in all of these instructions, including the content you add or edit in various files.

  2. Move the node_modules, public, and src folders into the new subfolder.

  3. Move the package-lock.json, package.json, and tsconfig.json into the new subfolder. The project structure should now look like the following:

    |-- .vscode/
    |-- appPackage/
    |-- build\appPackage/
    |-- env/
    |-- infra/
    |-- tab/
    |-- |-- node_modules/
    |-- |-- public/
    |-- |-- src/
    |-- |-- package-lock.json
    |-- |-- package.json
    |-- |-- tsconfig.json
    |-- gitignore
    |-- teamsapp.local.yml
    |-- teamsapp.yml
    
  4. In the package.json that you just moved to the tab folder, delete the script named "dev:teamsfx" from the "scripts" object. This script is added to a new package.json in the next step.

  5. Create a new file named package.json in the root of the project and give it the following content:

    {
        "name": "CombinedTabAndAddin",
        "version": "0.0.1",
        "author": "Contoso",
        "scripts": {
            "dev:teamsfx": "env-cmd --silent -f .localSettings npm run start:tab",
            "build:tab": "cd tab && npm run build",
            "install:tab": "cd tab && npm install",
            "start:tab": "cd tab && npm run start",
            "test": "echo \"Error: no test specified\" && exit 1"
        },
        "devDependencies": {
            "@microsoft/teamsfx-cli": "^1.2.3",
            "@microsoft/teamsfx-run-utils": "alpha",
            "env-cmd": "^10.1.0",
            "office-addin-dev-settings": "^2.0.3",
            "ncp": "^2.0.0"
        }
    }
    
  6. Change the "name", "version", and "author" properties, as needed.

  7. Open the teamsapp.local.yml file in the root of the project and find the line args: install --no-audit. Change this to args: run install:tab --no-audit.npm

  8. Open TERMINAL in Visual Studio Code. Navigate to the root of the project and run npm install. Among other things, a new node_modules folder is in the project root.

  9. Next run npm install:tab. Among other things, a new node_modules folder will be created in the tab folder, if there isn't one already.

  10. Verify that you can sideload the tab with the following steps:

    1. Select View | Run in Visual Studio Code.
    2. In the RUN AND DEBUG drop down menu, select the top option, Debug (Edge), and then press F5. The project will build and run. This process may take a couple of minutes. Eventually, Teams opens in a browser with a prompt to add your tab app.
    3. Select Add.
    4. To stop debugging and uninstall the app, select Run | Stop Debugging in Visual Studio Code.

Create an Outlook Add-in project

  1. Open a second instance of Visual Studio Code.

  2. With Teams Toolkit open in Visual Studio Code, select Create a new app.

  3. In the Select an option drop down, select Start with an Outlook add-in, and then select Outlook Taskpane Add-in (preview).

  4. Give a name (with no spaces) to the project when prompted and Teams Toolkit will create the project with basic files and scaffolding and open it in a separate Visual Studio Code window. You will used this project as a source for files and markup that you add to the Teams project.

  5. Although you won't be developing this project, verify that it can be sideloaded from Visual Studio Code before you continue. Use the following steps:

    1. First, make sure Outlook desktop is closed.
    2. In Visual Studio Code, open the Teams Toolkit.
    3. In the ACCOUNTS section, verify that you are signed into Microsoft 365.
    4. Select View | Run in Visual Studio Code. In the RUN AND DEBUG drop down menu, select the option, Outlook Desktop (Edge Chromium), and then press F5. The project builds and a Node dev-server window opens. This process may take a couple of minutes. Eventually, Outlook desktop will open.
    5. Open the Inbox of your Microsoft 365 account identity and open any message. A Contoso Add-in tab with two buttons will appear on the Home ribbon (or the Message ribbon, if you have opened the message in its own window).
    6. Click the Show Taskpane button and a task pane opens. Click the Perform an action button and a small notification appears near the top of the message.
    7. To stop debugging and uninstall the add-in, select Run | Stop Debugging in Visual Studio Code.

Merge the manifest

The Teams app's manifest is generated at debug-and-sideload time (or build time) from the file manifest.json in the \appPackage folder of the Teams project. This file is actually a kind of template for a manifest. In this article it is referred to as the "template" or "manifest template". Most of the markup is hardcoded into the template, but there are also some configuration files that contain data that gets injected into the final generated manifest. In this procedure, you do the following:

  • Copy markup from the add-in's manifest to the Teams app's manifest template.
  • Edit the configuration files.

Unless specified otherwise, the file you change is \appPackage\manifest.json.

  1. Copy the "$schema" and "manifestVersion" property values from the add-in's manifest to the corresponding properties of the Teams app's manifest template file.

  2. Adjust the "name.full", "description.short", and "description.full" property values as needed to take account of the fact that an Outlook add-in is part of the app.

  3. Do the same for the "name.short" value. We recommend that you keep the ${{TEAMSFX_ENV}} on the end of the name. This variable is replaced with "local" when you are debugging on localhost and with "dev" when you are either debugging from a remote domain or in production mode. (Historically, Office Add-in developer documentation has used the term "dev" or "dev mode" to refer to running the add-in on a localhost. It has used the term "prod" or "production mode" to refer to running the add-in on a remote host for staging or production. Teams developer documentation has used the term "local" to refer to running the add-in on a localhost, and the term "dev" to refer to running the add-in on a remote host for remote debugging, which is usually called "staging". We are working on getting the terminology consistent.)

    The following is an example:

    "short": "Fabrikam Tab and Add-in-${{TEAMSFX_ENV}}",
    

    Notes: The "name.short" value appears in both the Teams tab capability and the Outlook add-in. Examples:

    • It is the label under the launch button of the Teams tab.
    • It is content of the title bar of the add-in's task pane.
  4. If you changed the "name.short" value from its default (which is the name of the project followed by the ${{TEAMSFX_ENV}} variable), make exactly the same change in all places where the project name appears in the following two files in the root of the project: teamsapp.yml and teamsapp.local.yml.

  5. If there is no "authorization.permissions.resourceSpecific" array in the Teams manifest template, copy it from the add-in manifest as a top-level property. If there already is one in the Teams template, copy any objects from the array in the add-in manifest to the array in the Teams template. The following is an example:

    "authorization": {
        "permissions": {
            "resourceSpecific": [
                {
                    "name": "MailboxItem.Read.User",
                    "type": "Delegated"
                }
            ]
        }
    },
  6. In the .env.local file, find the lines that assign values to the TAB_DOMAIN and TAB_ENDPOINT variables. Add the following lines immediately below them:

    ADDIN_DOMAIN=localhost:53000
    ADDIN_ENDPOINT=https://localhost:53000
    

    NOTE: During the early preview phase, these variables are set to the same string as the two TAB_... variables. It is not possible at this time to host the add-in and the tab capability on distinct domains.

  7. Add the following line to the .env.dev file, just below the TAB_ENDPOINT= ... line:

    ADDIN_ENDPOINT=
    
  8. Add the following two lines to the end of the \infra\azure.bicep file:

    output ADDIN_DOMAIN string = siteDomain
    output ADDIN_ENDPOINT string = 'https://${siteDomain}'
    
  9. In the Teams manifest template, add the placeholder "${{ADDIN_DOMAIN}}", to the top of the "validDomains" array. The Teams Toolkit will replace this with a localhost domain when you are developing locally. When you deploy the finished combined app to staging or production as described below in Move the application to Azure, Teams Toolkit will replace the placeholder with the staging/production URI. The following is an example:

    "validDomains": [
        "${{ADDIN_DOMAIN}}",
        
        // other domains or placeholders
    ],
  10. Copy the entire "extensions" property from the add-in's manifest into the Teams app manifest template as a top-level property.

  11. In the Teams app manifest template, replace every occurrence of "localhost:3000" with "localhost:53000".

Copy the Outlook Add-in files to the Teams app project

  1. Create a top-level folder called "add-in" in the Teams app project.

  2. Copy the following files and folders from the add-in project to the "add-in" folder of the Teams app project.

    • /assets
    • /src
    • .eslintrc.json
    • babel.config.json
    • package-lock.json
    • package.json
    • tsconfig.json
    • webpack.config.js

    NOTE: Do not copy over the manifest.json file.

    Your folder structure should now look like the following:

    |-- .vscode/
    |-- add-in/
    |-- |-- assets/
    |-- |-- src/
    |-- |-- |-- commands/
    |-- |-- |-- taskpane/
    |-- |-- .eslintrc.json
    |-- |-- babel.config.json
    |-- |-- package-lock.json
    |-- |-- package.json
    |-- |-- tsconfig.json
    |-- |-- webpack.config.js
    |-- appPackage/
    |-- build\appPackage/
    |-- env/
    |-- infra/
    |-- node_modules/
    |-- tab/
    |-- |- node_modules/
    |-- |-- public/
    |-- |-- src/
    |-- |-- package-lock.json
    |-- |-- package.json
    |-- |-- tsconfig.json
    |-- gitignore
    |-- package.json
    |-- teamsapp.local.yml
    |-- teamsapp.yml
    

Edit the tooling configuration files

  1. Open the package.json file in the root of the project.

  2. Add the following scripts to the "scripts" object:

    "install:add-in": "cd add-in && npm install",
    "postinstall": "install:add-in && install:tab",
    "build:add-in": "cd add-in && npm run build",
    "build:add-in:dev": "cd add-in && npm run build:dev",
    "build": "npm run build:tab && npm run build:add-in",
    "postbuild": "ncp tab/build build && ncp add-in/dist build"
    
  3. Open the package.json file in the add-in folder (not the tab folder, and not the root of the project).

  4. In the "config" object, change the "dev_server_port" value to 53000.

  5. Several of the scripts in the "scripts" object have a manifest.json parameter like the following.

    "start": "office-addin-debugging start manifest.json",
    "start:desktop": "office-addin-debugging start manifest.json desktop",
    "start:web": "office-addin-debugging start manifest.json web",
    "stop": "office-addin-debugging stop manifest.json",
    "validate": "office-addin-manifest validate manifest.json",
    

    In the "start", "start:desktop", and "start:web" scripts, change manifest.json to ../build/AppPackage/appPackage.local.zip. When you are done, they should look like this:

    "start": "office-addin-debugging start ../build/AppPackage/appPackage.local.zip",
    "start:desktop": "office-addin-debugging start ../build/AppPackage/appPackage.local.zip desktop",
    "start:web": "office-addin-debugging start ../build/AppPackage/appPackage.local.zip web",
    

    In the "validate" and "stop" scripts, change the parameter to ../build/AppPackage/manifest.local.json. When you are done, they should look like this:

    "stop": "office-addin-debugging stop ../build/AppPackage/manifest.local.json",
    "validate": "office-addin-manifest validate ../build/AppPackage/manifest.local.json",
    
  6. In Visual Studio Code, open the TERMINAL. Navigate to the add-in folder, and then run the command npm install.

  7. In the add-in folder, open the webpack.config.js file.

  8. Change the line from: "manifest*.json", to from: "../build/appPackage/manifest*.json",.

  9. Near the top of the webpack.config.js file, there is a line that assigns a localhost URL with port 3000 to the urlDev constant. Change the value from 3000 to 53000.

  10. Near the end of the webpack.config.js file there is a line that assigns a value to the devServer.port property. Change the value from 3000 to 53000.

  11. In the root of project, open the teamsapp.local.yml file and find the configureApp section. Use the # character to comment out the lines that validate the manifest template. This is necessary because the Teams manifest validation system is not yet compatible with the changes you made to the manifest template. When you are done, the configureApp section should begin like the following:

    configureApp:
      - uses: file/updateEnv # Generate env to .env file
        with:
          envs:
            TAB_DOMAIN: localhost:53000
            TAB_ENDPOINT: https://localhost:53000
    #  - uses: teamsApp/validate
    #    with:
    #      manifestPath: ./appPackage/manifest.template.json # Path to manifest template
    
    # remainder of the section omitted
    
    
  12. Open the .vscode\tasks.json file in the add-in project and copy all of the tasks in the "tasks" array. Add them to "tasks" array of the same file in the Teams project. Do not remove any of the tasks that are already there. Be sure all tasks are separated by commas.

  13. In each of the task objects that you just copied, add the following "options" property to ensure that these tasks run in the add-in folder.

    "options": {
        "cwd": "${workspaceFolder}/add-in/"
    },
    

    For example, the "Debug: Outlook Desktop" task should like the following when you are done.

    {
        "label": "Debug: Outlook Desktop",
        "type": "npm",
        script": "start:desktop -- --app outlook",
        "presentation": {
            "clear": true,
            "panel": "dedicated",
        },
        "problemMatcher": [],
        "options": {
            "cwd": "${workspaceFolder}/add-in/"
        }
    }
    
  14. Add the following task to the "tasks" array in the .vscode\tasks.json file of the project. Note the following about this markup:

    • It adds a "Start Add-in Locally" task that combines the tab app's "Create resources" task with the add-in's debugging task and specifies that they must run in that order.
    • The "Create resources" task generates the final manifest.
    {
        "label": "Start Add-in Locally",
        "dependsOn": [
            "Create resources",
            "Debug: Outlook Desktop"
        ],
        "dependsOrder": "sequence"
    },
    
  15. Open the .vscode\launch.json file in the project, which configures the RUN AND DEBUG UI in Visual Studio Code and add the following object to the top of the "configurations" array.

    {
        "name": "Outlook Desktop (Edge Chromium)",
        "type": "msedge",
        "request": "attach",
        "port": 9229,
        "timeout": 600000,
        "webRoot": "${workspaceRoot}/add-in/",
        "preLaunchTask": "Start Add-in Locally",
        "postDebugTask": "Stop Debug"
    },
    
  16. Verify that you can sideload the add-in capability of the Teams app to Outlook with the following steps:

    1. First, make sure Outlook desktop is closed.
    2. In Visual Studio Code, open the Teams Toolkit.
    3. In the ACCOUNTS section, verify that you are signed into Microsoft 365.
    4. Select View | Run in Visual Studio Code. In the RUN AND DEBUG drop down menu, select the option, Outlook Desktop (Edge Chromium), and then press F5. The project builds and a Node dev-server window opens. This process may take a couple of minutes. Eventually, Outlook desktop will open.
    5. Open the Inbox of your Microsoft 365 account identity and open any message. A Contoso Add-in tab with two buttons will appear on the Home ribbon (or the Message ribbon, if you have opened the message in its own window).
    6. Click the Show Taskpane button and a task pane opens. Click the Perform an action button and a small notification appears near the top of the message.
    7. To stop debugging and uninstall the add-in, select Run | Stop Debugging in Visual Studio Code.

Move the application to Azure

  1. Open the teamsapp.yml file in the root of the project and find the line deploymentName: Create-resources-for-tab. Change it to deploymentName: Create-resources-for-tab-and-addin.

  2. In the same file, Replace the entire deploy: section with the following code. These changes take account of the new folder structure and the fact that both add-in and tab files need to be deployed.

    deploy:
      - name: InstallAllCapabilities
        uses: cli/runNpmCommand # Run npm command
        with:
          args: install
    
      - name: BuildAllCapabilities
        uses: cli/runNpmCommand # Run npm command
        with:
          args: run build --if-present
    
      - name: DeployToAzure
        uses: azureStorage/deploy # Deploy bits to Azure Storage Static Website
        with:
          workingDirectory: .
          distributionPath: ./build # Deploy base folder
          resourceId: ${{TAB_AZURE_STORAGE_RESOURCE_ID}} # The resource id of the cloud resource to be deployed to
    
  3. In Visual Studio Code open the Teams Toolkit and in the ACCOUNTS section be sure you are signed into your Azure account. For more information about signing in, open Exercise - Create Azure resources to host a Teams tab app and scroll to the Sign in to Azure in Teams Toolkit section.

  4. In the DEPLOYMENT section of Teams Toolkit, select Provision in the cloud. It may take several minutes.

  5. When provisioning completes, select Deploy to the cloud to deploy your app code to Azure.

Run the tab capability from the remote deployment

  1. Select View | Run in Visual Studio Code and in the drop down, select one of the following:

    • Launch Remote (Edge)
    • Launch Remote (Chrome)
  2. Press F5 to preview your Teams tab capability.

Run the add-in capability from the remote deployment

  1. Copy the production URL from the ADDIN_ENDPOINT in env/.env.dev file.
  2. Edit \add-in\webpack.config.js file and change urlProd constant value to the value you just copied. Please note to add a '/' at the end of the URL.
  3. In the Visual Studio Code TERMINAL, navigate to the root of the project, and then run npm run build:add-in.
  4. Copy the file \add-in\dist\manifest.dev.json to the \appPackage folder.
  5. Rename the copy in the \appPackage folder to "manifest.addinPreview.json".
  6. In the TERMINAL, run npx office-addin-dev-settings sideload .\appPackage\manifest.addinPreview.json. This process may take a couple of minutes. Eventually, Outlook desktop will open. (If you are prompted to install office-addin-dev-settings, respond "yes".)
  7. Open the Inbox of your Microsoft 365 account identity and open any message. A Contoso Add-in tab with two buttons will appear on the Home ribbon (or the Message ribbon, if you have opened the message in its own window).
  8. Click the Show Taskpane button and a task pane opens. Click the Perform an action button and a small notification appears near the top of the message.

What’s next

There are other commonly suggested next steps, for example:

⚠️ **GitHub.com Fallback** ⚠️