Migrating from Connectors to Workflows Webhooks for Microsoft Teams!
A Comprehensive Guide to Microsoft Teams Messaging with Workflows Webhooks
You may have heard about the upcoming deprecation of Microsoft Teams Connectors webhooks in the near future by Microsoft. With this change, we need to transition to using “Workflows” webhooks, a feature provided by Microsoft that offers similar functionality for sending messages to Microsoft Teams channels. Workflows webhooks come with additional features and increased security.
In this blog, I will delve into how we can use these “Workflows Webhooks” to send messages to Microsoft Teams channels from anywhere. We will explore the steps required to implement this, including creating webhook URLs using Workflows and using an AWS Lambda function to send messages/notifications to Microsoft Teams channels.
Creating Workflows Webhook URLs
Creating Workflows webhook URLs is straightforward, involving just a few clicks, as shown in the screenshots below. However, it’s important to note that when you create a Workflows webhook URL for any Microsoft Teams channel using your account, your identity becomes tied to these webhook URLs (unlike the “Connectors Webhooks”). This feature by Microsoft has its pros and cons: while it provides accountability, it also means that if you leave the organization or face issues with your account, your notifications might be affected. To mitigate this, you can create a standard user account and use it to generate Workflows webhook URLs. These webhooks will then be tied to a single, standardized user.
Steps to Create the Webhook URL Using Workflows
1. Access Workflows in Microsoft Teams: Go to the Workflows section in Microsoft Teams. You will find various pre-built templates provided by Microsoft to support a wide range of use cases. For our purposes, search for and select the “Post to a channel when a webhook request is received” template.
2. Configure the Workflow: Click on the template and give the flow a suitable name. In the Sign-in step, choose the account that will be used to send notifications to the channels (either a standard account for all notifications or your personal Microsoft Teams account).
3. Select Team and Channel: On the next page, select the team and associated channel where you want to configure this webhook to allow messaging from anywhere. Once you click on “Create Flow,” a “Webhook URL” will be generated. This URL can be used to send messages to the associated channel from anywhere. (Note: If you are using a standard user account, ensure it is a member of the Microsoft Teams channel to select it during this step).
Using AWS Lambda for Notifications
I use an AWS Lambda function to which we can pass the webhook URL, the title of the message, and the content of the message. This Lambda function posts the message to the respective Microsoft Teams channels with the provided title and content.
The webhook URL is stored in the SSM Parameter Store with the channel names in JSON format (e.g., "Channel_Name": "Webhook_URL"
). This allows you to pass only the channel name, title, and content when calling the Lambda function. The Lambda function will fetch the respective channel's webhook URL from the SSM Parameter Store and use it to send the message.
Lambda Code:
import sys
import logging
import os
import json
import urllib3
import boto3
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
runtime_region = os.environ['AWS_REGION']
http = urllib3.PoolManager()
session = boto3.Session(region_name=runtime_region)
ssm = session.client('ssm')
channels = ssm.get_parameter(Name='<<SSM Channel Address>>', WithDecryption=True)['Parameter']['Value']
channels = json.loads(channels)
def send_teams(webhook_url: str, content: str, title: str, color: str = "000000") -> int:
msg = {
"type": "message",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"contentUrl": None,
"content": {
"version": "1.2",
"type": "AdaptiveCard",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": title,
"size": "ExtraLarge",
"weight": "Bolder",
"wrap": True,
"color": color,
"horizontalAlignment": "Left",
"spacing": "Large"
}
],
"style": "emphasis",
"bleed": True
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": content,
"wrap": True,
"isSubtle": False,
"spacing": "Medium"
}
]
}
]
}
}
]
}
encoded_msg = json.dumps(msg).encode('utf-8')
response = http.request('POST', webhook_url, body=encoded_msg, headers={'Content-Type': 'application/json'})
return response.status
def lambda_handler(event, context):
content = event.get("content")
title = event.get("title")
color = event.get("color", "000000")
channel_name = event.get("channel_name")
webhook_url = channels.get(channel_name)
try:
print(event)
if not webhook_url:
raise ValueError(f"Webhook URL not found for channel: {channel_name}")
response_status = send_teams(webhook_url, content, title, color)
return {
'statusCode': response_status,
'body': json.dumps(title)
}
except Exception as error:
logger.error(f"Error: {error}")
return {
'statusCode': 500,
'body': str(error)
}
Example Input to Lambda Function:
{
"content": "This is the area where your content will be displayed",
"title": "This is your TITLE!",
"color": "00ff01",
"channel_name": "My_Channel"
}
Example Message on your MSTeams Channel:
Conclusion
Once you run the Lambda function by passing the input, you will receive the message in your Microsoft Teams channel like above. That’s all you need to do to set up messaging for Microsoft Teams channels. You can now use this feature in any of your AWS services, such as other Lambda functions, data pipelines, or CI/CD pipelines running on AWS infrastructure. Just invoke this notification Lambda function with the appropriate content for your flow (e.g., CI/CD pipeline completed/failed, etc.) 🙂