diff --git a/docs/configuration.md b/docs/configuration.md index 992e1fe425..95ac055dde 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -920,7 +920,18 @@ tls_config: ### `` -Microsoft Teams notifications are sent via the [Incoming Webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) API endpoint. +Microsoft Teams notifications are sent via the [Workflow](https://support.microsoft.com/en-us/office/creating-a-workflow-from-a-channel-in-teams-242eb8f2-f328-45be-b81f-9817b51a5f0e). + +#### How to create a workflow + +1. Select the workflow template, `Post to a channel when a webhook request is received` +2. Select `Microsoft Teams Team` you want to receive the notification +3. Select `Microsoft Teams Channel` you want to receive the notification + +After that, you can get the webhook URL. + +A Power Automate license is required to use this feature. You can get details +from [Types of Power Automate licenses](https://learn.microsoft.com/en-us/power-platform/admin/power-automate-licensing/types) and [Office 365 licenses](https://learn.microsoft.com/en-us/power-platform/admin/power-automate-licensing/faqs#what-power-automate-capabilities-are-included-in-office-365-licenses). ```yaml # Whether to notify about resolved alerts. @@ -934,6 +945,7 @@ Microsoft Teams notifications are sent via the [Incoming Webhooks](https://learn # Message title template. [ title: | default = '{{ template "msteams.default.title" . }}' ] +# DEPRECATED: Will be removed in future release. # Message summary template. [ summary: | default = '{{ template "msteams.default.summary" . }}' ] diff --git a/notify/msteams/msteams.go b/notify/msteams/msteams.go index d71e108144..d69a485ad9 100644 --- a/notify/msteams/msteams.go +++ b/notify/msteams/msteams.go @@ -35,9 +35,9 @@ import ( ) const ( - colorRed = "8C1A1A" - colorGreen = "2DC72D" - colorGrey = "808080" + colorRed = "Attention" + colorGreen = "Good" + colorGrey = "Warning" ) type Notifier struct { @@ -50,14 +50,33 @@ type Notifier struct { postJSONFunc func(ctx context.Context, client *http.Client, url string, body io.Reader) (*http.Response, error) } -// Message card reference can be found at https://learn.microsoft.com/en-us/outlook/actionable-messages/message-card-reference. +// https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#adaptivecarditemschema +type Content struct { + Schema string `json:"$schema"` + Type string `json:"type"` + Version string `json:"version"` + Body []Body `json:"body"` +} + +type Body struct { + Type string `json:"type"` + Text string `json:"text"` + Weight string `json:"weigth,omitempty"` + Size string `json:"size,omitempty"` + Wrap bool `json:"wrap,omitempty"` + Style string `json:"style,omitempty"` + Color string `json:"color,omitempty"` +} + +type Attachment struct { + ContentType string `json:"contentType"` + ContentURL *string `json:"contentUrl"` // Use a pointer to handle null values + Content Content `json:"content"` +} + type teamsMessage struct { - Context string `json:"@context"` - Type string `json:"type"` - Title string `json:"title"` - Summary string `json:"summary"` - Text string `json:"text"` - ThemeColor string `json:"themeColor"` + Type string `json:"type"` + Attachments []Attachment `json:"attachments"` } // New returns a new notifier that uses the Microsoft Teams Webhook API. @@ -102,10 +121,6 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) if err != nil { return false, err } - summary := tmpl(n.conf.Summary) - if err != nil { - return false, err - } alerts := types.Alerts(as...) color := colorGrey @@ -128,12 +143,33 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } t := teamsMessage{ - Context: "http://schema.org/extensions", - Type: "MessageCard", - Title: title, - Summary: summary, - Text: text, - ThemeColor: color, + Type: "message", + Attachments: []Attachment{ + { + ContentType: "application/vnd.microsoft.card.adaptive", + ContentURL: nil, + Content: Content{ + Schema: "http://adaptivecards.io/schemas/adaptive-card.json", + Type: "AdaptiveCard", + Version: "1.2", + Body: []Body{ + { + Type: "TextBlock", + Text: title, + Weight: "Bolder", + Size: "Medium", + Wrap: true, + Style: "heading", + Color: color, + }, + { + Type: "TextBlock", + Text: text, + }, + }, + }, + }, + }, } var payload bytes.Buffer diff --git a/notify/msteams/msteams_test.go b/notify/msteams/msteams_test.go index 80f9439173..6907363370 100644 --- a/notify/msteams/msteams_test.go +++ b/notify/msteams/msteams_test.go @@ -78,9 +78,8 @@ func TestMSTeamsTemplating(t *testing.T) { { title: "full-blown message", cfg: &config.MSTeamsConfig{ - Title: `{{ template "msteams.default.title" . }}`, - Summary: `{{ template "msteams.default.summary" . }}`, - Text: `{{ template "msteams.default.text" . }}`, + Title: `{{ template "msteams.default.title" . }}`, + Text: `{{ template "msteams.default.text" . }}`, }, retry: false, }, @@ -91,20 +90,11 @@ func TestMSTeamsTemplating(t *testing.T) { }, errMsg: "template: :1: unclosed action", }, - { - title: "summary with templating errors", - cfg: &config.MSTeamsConfig{ - Title: `{{ template "msteams.default.title" . }}`, - Summary: "{{ ", - }, - errMsg: "template: :1: unclosed action", - }, { title: "message with templating errors", cfg: &config.MSTeamsConfig{ - Title: `{{ template "msteams.default.title" . }}`, - Summary: `{{ template "msteams.default.summary" . }}`, - Text: "{{ ", + Title: `{{ template "msteams.default.title" . }}`, + Text: "{{ ", }, errMsg: "template: :1: unclosed action", },