Skip to content

Commit 1fc166c

Browse files
MS Teams: Auto-detect Power Automate and disable file attachments (#1995)
* Fix MS Teams sink to respect send_svg parameter The MS Teams sink was embedding base64-encoded images in the Adaptive Card payload, causing 'payload too large' errors with Power Automate webhooks (which have a strict 28KB limit). Other sinks (Slack, Discord, Jira, Zulip, etc.) already check the send_svg parameter to filter out images, but MS Teams was missing this check. Changes: - Pass send_svg parameter from MsTeamsSink to MsTeamsSender - Filter image FileBlocks when send_svg=False using is_image() helper - Add documentation for the send_svg setting Fixes #1994 * Add docstring to send_finding_to_ms_teams for CI coverage * Add send_files parameter to MS Teams sink to handle 28KB limit Replace the incorrectly used send_svg parameter with send_files: - send_svg was designed only for SVG files (see commit e354c48) - MS Teams 28KB limit affects all file types, not just SVGs - Follow existing pattern from Telegram, Pushover, YaMessenger sinks Changes: - Add send_files: bool = True to MsTeamsSinkParams - Update sender.py to filter all files when send_files is False - Remove incorrect is_image import from sender.py - Add docstring to write_finding for CodeRabbit coverage - Update documentation with new parameter name * Auto-detect Power Automate URLs and disable file attachments - Change send_files from bool to Optional[bool] with None default - Add _is_power_automate_url() helper to detect Power Automate webhooks - Auto-disable files for Power Automate URLs (*.api.powerplatform.com) - Keep files enabled for legacy webhooks (*.webhook.office.com) - Explicit send_files: true/false always overrides auto-detection - Update documentation with auto-detection behavior
1 parent ccf0065 commit 1fc166c

4 files changed

Lines changed: 75 additions & 1 deletion

File tree

docs/configuration/sinks/ms-teams.rst

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,35 @@ For example:
9393
- ms_teams_sink:
9494
name: main_ms_teams_sink
9595
webhook_url: teams-incoming-webhook
96-
prefer_redirect_to_platform: false
96+
prefer_redirect_to_platform: false
97+
98+
File Attachments
99+
-------------------------------------------------------------------
100+
101+
MS Teams Power Automate workflow webhooks have a strict 28KB payload size limit.
102+
Robusta automatically detects Power Automate URLs and disables file attachments
103+
to avoid exceeding this limit.
104+
105+
**Auto-detection behavior:**
106+
107+
- Power Automate URLs (``*.api.powerplatform.com``): files disabled by default
108+
- Legacy webhook URLs (``*.webhook.office.com``): files enabled by default
109+
110+
**Override auto-detection:**
111+
112+
You can explicitly control file attachments using the ``send_files`` parameter:
113+
114+
.. code-block:: yaml
115+
116+
sinksConfig:
117+
- ms_teams_sink:
118+
name: main_ms_teams_sink
119+
webhook_url: teams-incoming-webhook
120+
send_files: true # Force enable files (override auto-detection)
121+
# send_files: false # Force disable files
122+
123+
.. note::
124+
125+
When ``send_files`` is false (or auto-detected as false for Power Automate),
126+
all file attachments (images, logs, graphs, etc.) will not be included in
127+
the MS Teams message. Text-based content will still be sent normally.

src/robusta/core/sinks/msteams/msteams_sink.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ def __init__(self, sink_config: MsTeamsSinkConfigWrapper, registry):
1212
self.sink_config = sink_config.ms_teams_sink
1313

1414
def write_finding(self, finding: Finding, platform_enabled: bool):
15+
"""Write a finding to the MS Teams channel via webhook.
16+
17+
Args:
18+
finding: The finding to send to MS Teams.
19+
platform_enabled: Whether the Robusta platform is enabled for enhanced links.
20+
"""
1521
MsTeamsSender.send_finding_to_ms_teams(
1622
self.webhook_url,
1723
finding,
@@ -20,4 +26,5 @@ def write_finding(self, finding: Finding, platform_enabled: bool):
2026
self.account_id,
2127
self.webhook_override,
2228
self.sink_config.prefer_redirect_to_platform,
29+
self.sink_config.send_files,
2330
)

src/robusta/core/sinks/msteams/msteams_sink_params.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
class MsTeamsSinkParams(SinkBaseParams):
1111
webhook_url: str
1212
webhook_override: Optional[str] = None
13+
send_files: Optional[bool] = None # Auto-detect: False for Power Automate, True for legacy
1314

1415
@classmethod
1516
def _get_sink_type(cls):

src/robusta/integrations/msteams/sender.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import Optional
23

34
from robusta.core.reporting import (
45
BaseBlock,
@@ -18,6 +19,15 @@
1819
from robusta.integrations.msteams.msteams_msg import MsTeamsMsg
1920

2021

22+
def _is_power_automate_url(url: str) -> bool:
23+
"""Check if URL is a Power Automate workflow webhook (has 28KB payload limit).
24+
25+
Power Automate URLs contain '.api.powerplatform.com' or '/powerautomate/'.
26+
Legacy connector URLs use '*.webhook.office.com' and don't have the 28KB limit.
27+
"""
28+
return ".api.powerplatform.com" in url or "/powerautomate/" in url
29+
30+
2131
class MsTeamsSender:
2232
@classmethod
2333
def __to_ms_teams(cls, block: BaseBlock, msg: MsTeamsMsg):
@@ -61,15 +71,40 @@ def send_finding_to_ms_teams(
6171
account_id: str,
6272
webhook_override: str,
6373
prefer_redirect_to_platform: bool,
74+
send_files: Optional[bool] = None,
6475
):
76+
"""Send a finding to MS Teams via webhook.
77+
78+
Args:
79+
webhook_url: The MS Teams webhook URL.
80+
finding: The finding to send.
81+
platform_enabled: Whether the Robusta platform is enabled.
82+
cluster_name: The name of the cluster.
83+
account_id: The Robusta account ID.
84+
webhook_override: Optional webhook URL override pattern.
85+
prefer_redirect_to_platform: Whether to prefer platform links over Prometheus.
86+
send_files: Whether to include file attachments. None (default) auto-detects
87+
based on webhook URL: disabled for Power Automate (28KB limit), enabled
88+
for legacy webhooks. Explicit True/False overrides auto-detection.
89+
"""
6590
webhook_url = MsTeamsWebhookUrlTransformer.template(
6691
webhook_override=webhook_override, default_webhook_url=webhook_url, annotations=finding.subject.annotations
6792
)
93+
94+
# Auto-detect send_files based on webhook URL if not explicitly set
95+
if send_files is None:
96+
send_files = not _is_power_automate_url(webhook_url)
97+
6898
msg = MsTeamsMsg(webhook_url, prefer_redirect_to_platform)
6999
msg.write_title_and_desc(platform_enabled, finding, cluster_name, account_id)
70100

71101
for enrichment in finding.enrichments:
72102
files_blocks, other_blocks = cls.__split_block_to_files_and_all_the_rest(enrichment)
103+
104+
# Filter out all files when send_files is False to avoid 28KB payload limit
105+
if not send_files:
106+
files_blocks = []
107+
73108
for block in other_blocks:
74109
cls.__to_ms_teams(block, msg)
75110

0 commit comments

Comments
 (0)