Microsoft 365 Send

Microsoft 365 Send

Certified

Send an Adaptive Card to a Teams channel

Posts a Microsoft Adaptive Card to a Teams channel via the Microsoft Graph API. Unlike teams.TeamsIncomingWebhook, this task targets any channel by ID and returns the created message ID.

Sending a channel message requires DELEGATED (acting-as-user) authentication: set username and password so the task authenticates as a real user. App-only clientSecret (or pemCertificate) credentials are rejected by Microsoft Graph with an HTTP 403, since channel messages cannot be sent with application permissions alone.

yaml
type: io.kestra.plugin.microsoft365.teams.adaptivecards.Send

Send an Adaptive Card to a Teams channel

yaml
id: send_adaptive_card_to_channel
namespace: company.team

tasks:
  - id: send_card
    type: io.kestra.plugin.microsoft365.teams.adaptivecards.Send
    tenantId: "{{ secret('AZURE_TENANT_ID') }}"
    clientId: "{{ secret('AZURE_CLIENT_ID') }}"
    clientSecret: "{{ secret('AZURE_CLIENT_SECRET') }}"
    teamId: "{{ secret('TEAMS_TEAM_ID') }}"
    channelId: "{{ secret('TEAMS_CHANNEL_ID') }}"
    card: |
      {
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "type": "AdaptiveCard",
        "version": "1.4",
        "body": [
          {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "text": "Kestra Pipeline Report"
          },
          {
            "type": "FactSet",
            "facts": [
              { "title": "Flow", "value": "{{ flow.id }}" },
              { "title": "Status", "value": "{{ execution.state.current }}" },
              { "title": "Execution ID", "value": "{{ execution.id }}" }
            ]
          }
        ],
        "actions": [
          {
            "type": "Action.OpenUrl",
            "title": "View in Kestra",
            "url": "{{ kestra.url }}/ui/executions/{{ flow.namespace }}/{{ flow.id }}/{{ execution.id }}"
          }
        ]
      }

Send a card on flow failure

yaml
id: monitored_pipeline
namespace: company.team

tasks:
  - id: process
    type: io.kestra.plugin.scripts.shell.Commands
    commands:
      - ./run_pipeline.sh

errors:
  - id: alert_team
    type: io.kestra.plugin.microsoft365.teams.adaptivecards.Send
    tenantId: "{{ secret('AZURE_TENANT_ID') }}"
    clientId: "{{ secret('AZURE_CLIENT_ID') }}"
    clientSecret: "{{ secret('AZURE_CLIENT_SECRET') }}"
    teamId: "{{ secret('TEAMS_TEAM_ID') }}"
    channelId: "{{ secret('TEAMS_CHANNEL_ID') }}"
    card: |
      {
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "type": "AdaptiveCard",
        "version": "1.4",
        "body": [
          {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "color": "Attention",
            "text": "Pipeline Failed"
          },
          {
            "type": "TextBlock",
            "text": "Flow `{{ flow.id }}` failed at {{ execution.state.startDate }}.",
            "wrap": true
          }
        ]
      }

Send an Adaptive Card to a Teams channel using delegated (username/password) authentication

yaml
id: send_adaptive_card_delegated
namespace: company.team

tasks:
  - id: send_card
    type: io.kestra.plugin.microsoft365.teams.adaptivecards.Send
    tenantId: "{{ secret('AZURE_TENANT_ID') }}"
    clientId: "{{ secret('AZURE_CLIENT_ID') }}"
    username: "{{ secret('AZURE_USERNAME') }}"
    password: "{{ secret('AZURE_PASSWORD') }}"
    teamId: "{{ secret('TEAMS_TEAM_ID') }}"
    channelId: "{{ secret('TEAMS_CHANNEL_ID') }}"
    card: |
      {
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "type": "AdaptiveCard",
        "version": "1.4",
        "body": [
          {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "text": "Kestra Pipeline Report"
          },
          {
            "type": "FactSet",
            "facts": [
              { "title": "Flow", "value": "{{ flow.id }}" },
              { "title": "Status", "value": "{{ execution.state.current }}" }
            ]
          }
        ]
      }
Properties

Adaptive Card payload

The Adaptive Card JSON payload, rendered as a Pebble template before being sent. See https://adaptivecards.io/explorer/ for the schema reference.

Channel ID

The Teams channel identifier to post the card into

Team ID

The Microsoft Teams team identifier that owns the target channel

Client ID

Client ID of the Azure service principal. If you don't have a service principal, refer to create a service principal with Azure CLI.

Client Secret

Service principal client secret. Use this for Client Secret authentication. Provide clientId, tenantId, and clientSecret. Either clientSecret OR pemCertificate must be provided, not both.

Password

Password of the delegated user, used together with username for Resource Owner Password Credentials (ROPC) authentication. Requires the Azure AD app registration to have "Allow public client flows" enabled and the relevant delegated Graph permission granted (e.g. ChannelMessage.Send or Chat.ReadWrite).

PEM Certificate

Alternative authentication method using certificate-based authentication.
Use this for Client Certificate authentication. Provide clientId, tenantId, and pemCertificate.
Either clientSecret OR pemCertificate must be provided, not both.

Reference (ref) of the pluginDefaults to apply to this task.

Tenant ID

Username

Username of the delegated user to authenticate as (Resource Owner Password Credentials flow). Set this together with password for delegated (acting-as-user) authentication instead of app-only clientSecret/pemCertificate credentials. This is required for operations Microsoft Graph rejects under app-only auth, such as sending Teams channel or chat messages. Requires the Azure AD app registration to have "Allow public client flows" enabled and the relevant delegated Graph permission granted (e.g. ChannelMessage.Send or Chat.ReadWrite).

Created date time

ISO-8601 timestamp of when Microsoft Graph created the message

Message ID

Identifier of the sent chat message, usable to reply or look it up later