> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prisme.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Outlook (legacy)

> Read, send, and manage emails via Microsoft Graph API

<Note>
  This is the **legacy** Outlook connector (Microsoft Graph mail, application- or delegated-OAuth modes wired through `mcp-api-key` headers). It is superseded by the new **[Outlook](/apps-store/marketplace/connectors/outlook)** connector (App+MCP, tenant-context, central Microsoft Entra OAuth, with mail / calendar / contacts entity tools). Use the new Outlook connector for any new work — this page is kept for existing installations only.
</Note>

<img src="https://mintcdn.com/prismeai/Oqq72tWGTtxufvRl/images/connectors/outlook.png?fit=max&auto=format&n=Oqq72tWGTtxufvRl&q=85&s=9fe387aa1be3bd1ea4fcdf0d3bfda49f" alt="Outlook" width="96" height="96" noZoom style={{ float: "left", marginRight: "1.25rem", marginBottom: "0.5rem" }} data-path="images/connectors/outlook.png" />

The Outlook connector provides full access to Microsoft Outlook mailboxes via the Microsoft Graph API, enabling AI agents and automations to read, search, send, and manage emails.

<CardGroup cols={3}>
  <Card title="Read Operations" icon="inbox">
    List folders, messages, and attachments with filtering and pagination
  </Card>

  <Card title="Send Operations" icon="paper-plane">
    Send, reply, reply-all, forward emails with HTML support
  </Card>

  <Card title="Manage Messages" icon="folder-open">
    Move, copy, delete, and update message properties
  </Card>
</CardGroup>

## Choose your authentication mode

The connector supports two **mutually exclusive** authentication modes. Pick the one that matches your use case before configuring the connector.

<CardGroup cols={2}>
  <Card title="Application mode (app-only)" icon="building">
    A single Azure AD app acts on behalf of the workspace. Can reach any mailbox in the tenant (restrictable). No per-user login. Best for back-office automations and service accounts.
  </Card>

  <Card title="Delegated mode (OAuth per-user)" icon="user-check">
    Each end user signs into Microsoft once via an OAuth popup. Access is scoped to that user's own mailbox. Best for agents that act on behalf of the logged-in user.
  </Card>
</CardGroup>

| Aspect                 | Application mode                    | Delegated (OAuth) mode                          |
| ---------------------- | ----------------------------------- | ----------------------------------------------- |
| Azure permission type  | Application                         | Delegated                                       |
| Admin consent          | Required                            | Optional (user consent if tenant allows)        |
| Mailbox reach          | All tenant mailboxes (restrictable) | Connected user's mailbox only                   |
| Who authenticates      | No end-user login                   | Each user signs in once                         |
| `userId` tool argument | Required (target mailbox)           | Ignored (always the connected user)             |
| Token acquisition      | Client credentials per request      | Authorization code + PKCE; refresh token stored |
| Best for               | Back-office / service automations   | User-facing agents, per-user data               |

***

## Prerequisites

<Tabs>
  <Tab title="Application mode">
    ## Application mode

    * An **Azure AD Application** registered in your tenant
    * **Application permissions** granted (not Delegated):
      * `Mail.Read` — Read mail in all mailboxes
      * `Mail.ReadWrite` — Create drafts, update, delete, move, copy
      * `Mail.Send` — Send, reply, reply-all, forward
      * `MailboxSettings.Read` — Read mailbox settings
    * **Admin consent** granted for these permissions
    * A **client secret** created on the app registration

    <Note>
      **Minimal permissions:** If you only need read access, `Mail.Read` and `MailboxSettings.Read` are sufficient. Add `Mail.Send` and/or `Mail.ReadWrite` only if you use write tools.
    </Note>
  </Tab>

  <Tab title="Delegated (OAuth) mode">
    ## Delegated (OAuth) mode

    * An **Azure AD Application** registered in your tenant with a **Web** platform configured

    * A **Redirect URI** added to the app registration:

      ```
      {platformApiUrl}/workspaces/{workspaceId}/webhooks/oauthCallback
      ```

      Example (sandbox, workspace `oOFlMpO`):

      ```
      https://api.sandbox.prisme.ai/v2/workspaces/oOFlMpO/webhooks/oauthCallback
      ```

    * **Delegated permissions** granted (Microsoft Graph):
      * `Mail.Read`
      * `Mail.ReadWrite`
      * `Mail.Send`
      * `MailboxSettings.Read`
      * `User.Read` — sign-in and profile
      * `offline_access` — issue refresh tokens
      * `openid`, `profile`, `email` — ID token / user identity

    * A **client secret** (the connector uses the authorization code flow with PKCE as a **confidential client**, so "Allow public client flows" must stay **No**)

    * Either the tenant allows end-user consent, or an admin grants consent once to the delegated scopes above

    <Note>
      You can reuse the same Azure app registration for both modes, but the **permission types differ**: Application permissions for app-only mode, Delegated permissions for OAuth mode.
    </Note>
  </Tab>
</Tabs>

***

## OAuth flow (Delegated mode)

When Delegated mode is enabled, end users connect their Microsoft account through a built-in flow implemented by the `outlook-mcp` workspace.

<Steps>
  <Step title="User opens the connect page">
    The user visits `{pagesUrl}/connect-outlook`. The page shows a **Connect Outlook** button when OAuth is configured and the user has no active connection.
  </Step>

  <Step title="Initiate">
    The page (or the `initiateOAuth` webhook) generates a PKCE **code verifier / code challenge (S256)** and a CSRF **state**, stores them in the user scope, and builds the Microsoft authorize URL.
  </Step>

  <Step title="Microsoft login & consent">
    The user is redirected to `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize` and consents to the delegated scopes.
  </Step>

  <Step title="Callback & token exchange">
    Microsoft redirects back to `/webhooks/oauthCallback?code=...&state=...`. The workspace validates the `state`, exchanges the code (with the PKCE `code_verifier`) for tokens at `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token`, and stores:

    * `outlook_delegated_token` — platform secret, user scope, TTL = `expires_in`
    * `outlook_refresh_token` — platform secret, user scope, TTL = **90 days** (`7776000` s)
    * `user.outlook.oauth` — metadata only (`expiresAt`, `scope`, `authMethod: delegated`)
  </Step>

  <Step title="Automatic refresh">
    When the access token is about to expire, `refreshOAuthToken` silently exchanges the refresh token for a new access token (and rotates the refresh token if Microsoft returns a new one).
  </Step>

  <Step title="Disconnect">
    Users can call the `disconnectOAuth` webhook (or trigger the `disconnectOAuth` event) to clear all stored tokens and metadata.
  </Step>
</Steps>

<Note>
  **Security properties:**

  * PKCE (S256) protects the authorization code
  * CSRF `state` is validated on callback
  * Tokens are stored as **platform secrets** (opaque references), never as plain user metadata
  * `redirectTo` is validated against the platform host to prevent open-redirect attacks
</Note>

***

<Tabs>
  <Tab title="Usage as App">
    ## Usage as App

    ## Installation

    1. Go to **Apps** in your workspace
    2. Search for **Outlook App** and install it
    3. Configure the app instance for your chosen mode (Application or Delegated)

    ## Configuration

    <Tabs>
      <Tab title="Application mode">
        | Field                   | Value                                                 |
        | ----------------------- | ----------------------------------------------------- |
        | **Azure Client ID**     | Application (client) ID from Azure AD                 |
        | **Azure Client Secret** | Client secret value                                   |
        | **Azure Tenant ID**     | Directory (tenant) ID                                 |
        | **Default User ID**     | Email address or user object ID of the target mailbox |
      </Tab>

      <Tab title="Delegated (OAuth) mode">
        | Field                                          | Value                                                                                                            |
        | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
        | **OAuth Client ID** (`oauth.clientId`)         | Azure AD application (client) ID                                                                                 |
        | **OAuth Client Secret** (`oauth.clientSecret`) | Azure AD client secret                                                                                           |
        | **OAuth Tenant** (`oauth.tenant`)              | Directory (tenant) ID, or `common` / `organizations`                                                             |
        | **OAuth Scopes** (`oauth.scopes`)              | Default: `openid profile email offline_access Mail.Read Mail.Send Mail.ReadWrite MailboxSettings.Read User.Read` |

        `Default User ID` is **not used** in Delegated mode — each user operates on their own mailbox.
      </Tab>
    </Tabs>

    ## Available Automations

    The automation names and Graph permissions below are identical in both modes; only the **permission type** (Application vs Delegated) granted in Azure AD differs.

    ### Read Operations

    | Automation           | Description                                       | Graph permission     |
    | -------------------- | ------------------------------------------------- | -------------------- |
    | `listMailFolders`    | List all mail folders with message counts         | Mail.Read            |
    | `getMailFolder`      | Get folder details by ID or well-known name       | Mail.Read            |
    | `listMessages`       | List messages with filtering, pagination, sorting | Mail.Read            |
    | `getMessage`         | Get full message content and metadata             | Mail.Read            |
    | `searchMessages`     | Search messages using KQL syntax                  | Mail.Read            |
    | `listAttachments`    | List all attachments for a message                | Mail.Read            |
    | `getAttachment`      | Get attachment content as base64                  | Mail.Read            |
    | `getMailboxSettings` | Get timezone, locale, automatic replies           | MailboxSettings.Read |

    ### Send Operations

    | Automation        | Description                                      | Graph permission |
    | ----------------- | ------------------------------------------------ | ---------------- |
    | `sendMail`        | Send an email (to/cc/bcc, HTML/text, importance) | Mail.Send        |
    | `sendDraft`       | Send an existing draft message                   | Mail.Send        |
    | `replyMessage`    | Reply to a message                               | Mail.Send        |
    | `replyAllMessage` | Reply-all to a message                           | Mail.Send        |
    | `forwardMessage`  | Forward a message to recipients                  | Mail.Send        |

    ### Write Operations

    | Automation      | Description                                 | Graph permission |
    | --------------- | ------------------------------------------- | ---------------- |
    | `createDraft`   | Create a draft email in Drafts folder       | Mail.ReadWrite   |
    | `updateMessage` | Update properties (read status, importance) | Mail.ReadWrite   |
    | `deleteMessage` | Soft-delete (move to Deleted Items)         | Mail.ReadWrite   |
    | `moveMessage`   | Move message to another folder              | Mail.ReadWrite   |
    | `copyMessage`   | Copy message to another folder              | Mail.ReadWrite   |

    ## DSUL Examples

    ### List Messages

    ```yaml theme={null}
    - Outlook App.listMessages:
        userId: user@company.com   # Application mode only; ignored in Delegated mode
        folderId: inbox
        top: 10
        filter: "isRead eq false"
        output: messages
    ```

    ### Send an Email

    ```yaml theme={null}
    - Outlook App.sendMail:
        userId: user@company.com
        to: recipient@example.com
        subject: Meeting Follow-up
        body: "<p>Thank you for the meeting today.</p>"
        contentType: HTML
        output: result
    ```

    ### Search Messages

    ```yaml theme={null}
    - Outlook App.searchMessages:
        userId: user@company.com
        query: "from:john@example.com subject:project"
        top: 20
        output: results
    ```

    ### Reply to a Message

    ```yaml theme={null}
    - Outlook App.replyMessage:
        userId: user@company.com
        messageId: "{{messageId}}"
        comment: "Thanks for the update!"
        output: result
    ```
  </Tab>

  <Tab title="Usage as MCP">
    ## Usage as MCP

    ## MCP Setup

    1. Open your **Knowledges project**
    2. Go to **Advanced > Tools**
    3. Click **Add** and select the **MCP** tab
    4. Enter the MCP endpoint URL
    5. In the **Headers** field, add the credentials for your chosen mode

    <Tabs>
      <Tab title="Application mode headers">
        ```json theme={null}
        {
          "mcp-api-key": "your-mcp-api-key",
          "azure-client-id": "your-client-id",
          "azure-client-secret": "your-client-secret",
          "azure-tenant": "your-tenant-id"
        }
        ```

        The MCP server uses the client credentials flow against Microsoft Graph and targets the mailbox specified by `userId` (or the workspace default).
      </Tab>

      <Tab title="Delegated (OAuth) mode headers">
        ```json theme={null}
        {
          "mcp-api-key": "your-mcp-api-key",
          "auth-mode": "oauth"
        }
        ```

        No `azure-*` headers. The end user must have completed the OAuth flow once via `{pagesUrl}/connect-outlook`. If they haven't, the tool returns a structured error containing a `connectUrl` pointing to the connect page.

        <Warning>
          `auth-mode: oauth` **forces** Delegated mode and disables all fallbacks. If no valid delegated token is stored for the user, the request fails immediately with a `connectUrl` — it will not fall back to client credentials.
        </Warning>
      </Tab>
    </Tabs>

    <Note>
      The `mcp-api-key` value must match the **MCP API Key** secret configured in the workspace secrets (`mcpApiKey`).
    </Note>

    ## Authentication

    The MCP server resolves credentials in the following priority order (see `outlook-app/resolveAuth.yml`):

    1. `auth-mode: oauth` header → **requires** a stored delegated token for the user; no fallback
    2. `Authorization: Bearer <token>` header (pre-resolved Graph access token)
    3. `azure-client-id` / `azure-client-secret` / `azure-tenant` custom headers (Application mode)
    4. Stored OAuth delegated tokens (`user.outlook.oauth` + platform secrets), with automatic refresh
    5. Per-user credentials from `configureOutlook` (`user.outlook.credentials`)
    6. Workspace secrets client credentials (`azureClientId`, `azureClientSecret`, `azureTenant`)

    ### Workspace Secrets

    | Secret              | Used by          | Description                             |
    | ------------------- | ---------------- | --------------------------------------- |
    | `azureClientId`     | Application mode | Azure AD client ID                      |
    | `azureClientSecret` | Application mode | Azure AD client secret                  |
    | `azureTenant`       | Application mode | Azure AD tenant ID                      |
    | `defaultUserId`     | Application mode | Default mailbox email or user object ID |
    | `mcpApiKey`         | Both             | API key for authenticating MCP requests |

    Delegated mode reads its configuration from `config.oauth.*` (`clientId`, `clientSecret`, `tenant`, `scopes`), which by default resolves to the same Azure secrets above — the same app registration can serve both modes.

    ### Mailbox Targeting

    * **Application mode** — the `userId` tool argument (or `defaultUserId` workspace secret) selects which mailbox to act on. Resolution order: tool argument `userId` > workspace secret `defaultUserId`. If neither is set, the request fails.
      * **User Principal Name**: `user@yourdomain.com`
      * **User Object ID**: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
    * **Delegated (OAuth) mode** — `userId` is **ignored**. All calls run against `/me` — the mailbox of the user whose OAuth token is used.

    ## Available Tools

    ### Read Operations

    | Tool                 | Description                                       | Graph permission     |
    | -------------------- | ------------------------------------------------- | -------------------- |
    | `listMailFolders`    | List all mail folders with message counts         | Mail.Read            |
    | `getMailFolder`      | Get folder details by ID or well-known name       | Mail.Read            |
    | `listMessages`       | List messages with filtering, pagination, sorting | Mail.Read            |
    | `getMessage`         | Get full message content and metadata             | Mail.Read            |
    | `searchMessages`     | Search messages using KQL syntax                  | Mail.Read            |
    | `listAttachments`    | List all attachments for a message                | Mail.Read            |
    | `getAttachment`      | Get attachment content as base64                  | Mail.Read            |
    | `getMailboxSettings` | Get timezone, locale, automatic replies           | MailboxSettings.Read |

    ### Send Operations

    | Tool              | Description                                      | Graph permission |
    | ----------------- | ------------------------------------------------ | ---------------- |
    | `sendMail`        | Send an email (to/cc/bcc, HTML/text, importance) | Mail.Send        |
    | `sendDraft`       | Send an existing draft message                   | Mail.Send        |
    | `replyMessage`    | Reply to a message (comment or full body)        | Mail.Send        |
    | `replyAllMessage` | Reply-all to a message                           | Mail.Send        |
    | `forwardMessage`  | Forward a message to recipients                  | Mail.Send        |

    ### Write Operations

    | Tool            | Description                                             | Graph permission |
    | --------------- | ------------------------------------------------------- | ---------------- |
    | `createDraft`   | Create a draft email in Drafts folder                   | Mail.ReadWrite   |
    | `updateMessage` | Update properties (read status, importance, categories) | Mail.ReadWrite   |
    | `deleteMessage` | Soft-delete (move to Deleted Items)                     | Mail.ReadWrite   |
    | `moveMessage`   | Move message to another folder                          | Mail.ReadWrite   |
    | `copyMessage`   | Copy message to another folder                          | Mail.ReadWrite   |

    ## JSON-RPC Examples

    ### List Messages

    ```json theme={null}
    {
      "name": "listMessages",
      "arguments": {
        "userId": "user@company.com",
        "folderId": "inbox",
        "top": 10,
        "filter": "isRead eq false"
      }
    }
    ```

    ### Send an Email

    ```json theme={null}
    {
      "name": "sendMail",
      "arguments": {
        "userId": "user@company.com",
        "to": "recipient@example.com",
        "subject": "Meeting Follow-up",
        "body": "<p>Thank you for the meeting today.</p>",
        "contentType": "HTML"
      }
    }
    ```

    ### Search Messages

    ```json theme={null}
    {
      "name": "searchMessages",
      "arguments": {
        "userId": "user@company.com",
        "query": "from:john@example.com subject:project",
        "top": 20
      }
    }
    ```

    ## Output Formats

    All tools support an `outputFormat` parameter:

    * **`verbose`** (default) — Human-readable text for LLM consumption
    * **`structured`** — Machine-readable JSON in `structuredContent`
    * **`both`** — Both text and structured content
  </Tab>
</Tabs>

***

## Security: Restrict to One Mailbox (Application mode only)

<Note>
  This section applies only to **Application mode**. Delegated (OAuth) mode is already restricted to the consenting user's own mailbox and does not need an Application Access Policy.
</Note>

Application permissions grant access to **all mailboxes** in the tenant by default. To restrict this connector to a single mailbox, use an **Application Access Policy** in Exchange Online:

```powershell theme={null}
# 1. Connect to Exchange Online
Connect-ExchangeOnline

# 2. Create a mail-enabled security group with only the target mailbox
New-DistributionGroup -Name "OutlookMCP-Allowed" -Type Security -Members user@yourdomain.com

# 3. Restrict the Azure AD app to only access that group's mailboxes
New-ApplicationAccessPolicy -AppId "<your-azure-client-id>" `
  -PolicyScopeGroupId "OutlookMCP-Allowed" `
  -AccessRight RestrictAccess `
  -Description "Restrict Outlook connector to single mailbox"

# 4. Verify (may take up to 30 minutes to propagate)
Test-ApplicationAccessPolicy -AppId "<your-azure-client-id>" -Identity user@yourdomain.com
# Expected: Granted
```

<Warning>
  The PowerShell commands above are provided as general guidance. Always refer to the [official Microsoft documentation](https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access) for the most up-to-date syntax.
</Warning>

***

## Error Handling

| HTTP Status | Error                                                       | Solution                                                                                   |
| ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| 401         | Unauthorized (Application mode)                             | Verify `clientId`, `clientSecret`, `tenant`                                                |
| 401         | User not connected / expired refresh token (Delegated mode) | The response includes a `connectUrl` — the end user must (re)connect at `/connect-outlook` |
| 403         | Forbidden                                                   | Grant admin consent or check Application Access Policy                                     |
| 404         | Not Found                                                   | Verify user email/ID exists in tenant                                                      |
| 429         | Rate Limited                                                | Wait and retry                                                                             |

### Common Issues

**`AADSTS700016`** — App not found in the directory. Check tenant ID matches the app registration.

**`AADSTS65001`** — User has not consented to the required delegated scopes. Either enable user consent in the tenant or have an admin grant consent once.

**`MailboxNotEnabledForRESTAPI`** — The user needs an Exchange Online license assigned.

**`invalid_grant` on refresh** — The refresh token has expired (>90 days) or been revoked. The user must reconnect via `/connect-outlook`.

**`invalid_client`** — The Azure AD client secret is wrong or has expired. Rotate the secret in Azure AD and update the workspace configuration.

**`ErrorAccessDenied` with Application Access Policy** — The target mailbox is not in the allowed security group. Takes up to 30 minutes to propagate after policy changes.

## External Resources

<CardGroup cols={2}>
  <Card title="Microsoft Graph Mail API" icon="book" href="https://learn.microsoft.com/en-us/graph/api/resources/mail-api-overview">
    Official API documentation
  </Card>

  <Card title="OAuth 2.0 authorization code flow" icon="key" href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow">
    Microsoft identity platform — delegated auth code + PKCE
  </Card>

  <Card title="Delegated permissions reference" icon="user-shield" href="https://learn.microsoft.com/en-us/graph/permissions-reference">
    Microsoft Graph — delegated vs application permissions
  </Card>

  <Card title="Application Access Policies" icon="shield" href="https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access">
    Restrict mailbox access per application (app-only mode)
  </Card>

  <Card title="Graph Explorer" icon="flask" href="https://developer.microsoft.com/en-us/graph/graph-explorer">
    Test API calls interactively
  </Card>

  <Card title="MCP Specification" icon="robot" href="https://modelcontextprotocol.io">
    Model Context Protocol specification
  </Card>
</CardGroup>
