Skip to content

Instantly share code, notes, and snippets.

@chusiang
Last active July 22, 2024 03:50
Show Gist options
  • Save chusiang/895f6406fbf9285c58ad0a3ace13d025 to your computer and use it in GitHub Desktop.
Save chusiang/895f6406fbf9285c58ad0a3ace13d025 to your computer and use it in GitHub Desktop.
Post a message to Microsoft Teams with bash script.
#!/bin/bash
# =============================================================================
# Author: Chu-Siang Lai / chusiang (at) drx.tw
# Filename: teams-chat-post-for-workflows.sh
# Modified: 2024-07-22 11:44 (UTC+08:00)
# Description: Post a message to Microsoft Teams via "Post to a chat when a webhook request is received" workflows.
# Reference:
#
# - https://gist.github.com/chusiang/895f6406fbf9285c58ad0a3ace13d025
# - https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
# - https://adaptivecards.io/explorer/
# - https://adaptivecards.io/designer/
#
# =============================================================================
# Help.
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo 'Usage: teams-chat-post.sh "<webhook_url>" "<title>" "<color>" "<message>"'
exit 0
fi
# Webhook or Token.
WEBHOOK_URL=$1
if [[ "${WEBHOOK_URL}" == "" ]]; then
echo "No webhook_url specified."
exit 1
fi
shift
# Title .
TITLE=$1
if [[ "${TITLE}" == "" ]]; then
echo "No title specified."
exit 1
fi
shift
# Color.
COLOR=$1
if [[ "${COLOR}" == "" ]]; then
echo "No status specified."
exit 1
fi
shift
# Text.
TEXT=$*
if [[ "${TEXT}" == "" ]]; then
echo "No text specified."
exit 1
fi
ATTACHMENTS=$*
if [[ "${TEXT}" == "" ]]; then
echo "No text specified."
exit 1
fi
# Escape char: `'`, `"`, `\` .
MESSAGE=$(echo ${TEXT} | sed "s/'/\'/g" | sed 's/"/\"/g; s/\\/\\\\/g')
# Adaptive Cards of TextBlock - https://adaptivecards.io/explorer/TextBlock.html
JSON="{
\"type\": \"message\",
\"attachments\": [
{
\"contentType\": \"application/vnd.microsoft.card.adaptive\",
\"contentUrl\": null,
\"content\": {
\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.2\",
\"body\": [
{
\"type\": \"TextBlock\",
\"text\": \"${TITLE}\",
\"color\": \"${COLOR}\",
\"weight\": \"bolder\",
\"size\": \"large\",
\"wrap\": true
},
{
\"type\": \"TextBlock\",
\"text\": \"${MESSAGE}\",
\"color\": \"${COLOR}\",
\"size\": \"small\",
\"wrap\": true
}
]
}
}
]
}"
# Post to Microsoft Teams via curl.
curl \
--header "Content-Type: application/json" \
--request POST \
--data "${JSON}" \
"${WEBHOOK_URL}"
#!/bin/bash
# =============================================================================
# Author: Chu-Siang Lai / chusiang (at) drx.tw
# Filename: teams-chat-post.sh
# Modified: 2024-07-12 18:49 (UTC+08:00)
# Description: Post a message to Microsoft Teams via connectors, not support
# Power Automate workflows.
# Reference:
#
# - https://gist.github.com/chusiang/895f6406fbf9285c58ad0a3ace13d025
# - https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
# - Fixed for workflows edition: https://gist.github.com/chusiang/895f6406fbf9285c58ad0a3ace13d025?permalink_comment_id=5119162#gistcomment-5119162
#
# =============================================================================
# Help.
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo 'Usage: teams-chat-post.sh "<webhook_url>" "<title>" "<color>" "<message>"'
exit 0
fi
# Webhook or Token.
WEBHOOK_URL=$1
if [[ "${WEBHOOK_URL}" == "" ]]; then
echo "No webhook_url specified."
exit 1
fi
shift
# Title .
TITLE=$1
if [[ "${TITLE}" == "" ]]; then
echo "No title specified."
exit 1
fi
shift
# Color.
COLOR=$1
if [[ "${COLOR}" == "" ]]; then
echo "No status specified."
exit 1
fi
shift
# Text.
TEXT=$*
if [[ "${TEXT}" == "" ]]; then
echo "No text specified."
exit 1
fi
# Convert formating.
MESSAGE=$(echo ${TEXT} | sed 's/"/\"/g' | sed "s/'/\'/g")
JSON="{
\"title\": \"${TITLE}\",
\"themeColor\": \"${COLOR}\",
\"text\": \"${MESSAGE}\"
}"
# Post to Microsoft Teams.
curl -H "Content-Type: application/json" -d "${JSON}" "${WEBHOOK_URL}"
@atc0005
Copy link

atc0005 commented Oct 6, 2022

@ciroiriarte

The Event time, Severity and Operational data fields are "Facts", name/value pairs that are rendered in a table format.

@chusiang
Copy link
Author

chusiang commented Jul 9, 2024

Hi all, this first script of teams-chat-post.sh is not working with workflows of "Post to a channel when a webhook request is received" now.

This is a bad news.

Retirement of Office 365 connectors within Microsoft Teams

@ronnyheymans
Copy link

ronnyheymans commented Jul 9, 2024

If you create a new flow with workflows and change the json structure of the script it works again

create flow with following steps :

  • Open Workflows in teams
  • +new flow
  • choose notifications at the left
  • select "Post to a channel when a webhook request is received"
  • at the set up your flow part choose the team and channel where you want to post
  • create the flow

change ths JSON part in the script to the following :
JSON="{"type":"message","attachments":[{"contentType":"application/vnd.microsoft.card.adaptive","contentUrl":null,"content":{"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","type":"AdaptiveCard","version":"1.2","body":[{"type": "TextBlock","text": "${TITLE}"},{"type": "TextBlock","text": "${MESSAGE}"}]}}]}"

More info on the structure of an adaptive card : https://learn.microsoft.com/en-us/adaptive-cards/authoring-cards/getting-started
More info on webhook json body structure : https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#example
Adaptive Card designer : https://adaptivecards.io/designer/

@q2uantum
Copy link

If you create a new flow with workflows and change the json structure of the script it works again

create flow with following steps :

  • Open Workflows in teams
  • +new flow
  • choose notifications at the left
  • select "Post to a channel when a webhook request is received"
  • at the set up your flow part choose the team and channel where you want to post
  • create the flow

change ths JSON part in the script to the following : JSON="{"type":"message","attachments":[{"contentType":"application/vnd.microsoft.card.adaptive","contentUrl":null,"content":{"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","type":"AdaptiveCard","version":"1.2","body":[{"type": "TextBlock","text": "${TITLE}"},{"type": "TextBlock","text": "${MESSAGE}"}]}}]}"

More info on the structure of an adaptive card : https://learn.microsoft.com/en-us/adaptive-cards/authoring-cards/getting-started More info on webhook json body structure : https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#example Adaptive Card designer : https://adaptivecards.io/designer/

This didn't work for me, I got the following error:

{"error":{"code":"InvalidRequestContent","message":"The request content is not valid and could not be deserialized: 'Unexpected character encountered while parsing value: m. Path 'type', line 1, position 6.'."}

Any ideas @ronnyheymans ?

@ronnyheymans
Copy link

ronnyheymans commented Jul 10, 2024

@q2uantum It seems you made an error in de JSON declaration. Could it be you forgot to put \ before the " in your statement. I just saw they are removed in my post above. only the first and the last don't need a \

Screenshot : https://snipboard.io/pdzC3h.jpg

@q2uantum
Copy link

@ronnyheymans Thanks for the quick reply, that fixed the issue 👍

For clarity (if it posts correctly) this is what works:

JSON="{\"type\":\"message\",\"attachments\":[{\"contentType\":\"application/vnd.microsoft.card.adaptive\",\"contentUrl\":null,\"content\":{\"$schema\":\"http://adaptivecards.io/schemas/adaptive-card.json\",\"type\":\"AdaptiveCard\",\"version\":\"1.2\",\"body\":[{\"type\": \"TextBlock\",\"text\": \"${TITLE}\"},{\"type\": \"TextBlock\",\"text\": \"${MESSAGE}\"}]}}]}"

@ronnyheymans
Copy link

ronnyheymans commented Jul 10, 2024

@q2uantum Yep that's how it should be. If you want extra information you can use the designer to add fields and configure how they should look and then copy the json part to the statement here.

@q2uantum
Copy link

@ronnyheymans Do you know if its possible to extend the width of the workflow text box via the JSON script? As its cutting short the test that I used to be able to see via standard Webhook.

image

I can see in the designer there is a stretch option , would that work in the JSON as a variable ?

@ronnyheymans
Copy link

@q2uantum You have to enable wrap with "wrap": true on the block you want the complete text. So for example the following
{"type": "TextBlock","wrap": true,"text": "${MESSAGE}"}
I haven't found anything (so far) to enlarge the Adaptive card.

@q2uantum
Copy link

Thanks @ronnyheymans The wrap: true will help me for now. I will keep looking myself for options to enlarge the Adaptive card

@whanklee
Copy link

If you create a new flow with workflows and change the json structure of the script it works again

create flow with following steps :

  • Open Workflows in teams
  • +new flow
  • choose notifications at the left
  • select "Post to a channel when a webhook request is received"
  • at the set up your flow part choose the team and channel where you want to post
  • create the flow

change ths JSON part in the script to the following : JSON="{"type":"message","attachments":[{"contentType":"application/vnd.microsoft.card.adaptive","contentUrl":null,"content":{"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","type":"AdaptiveCard","version":"1.2","body":[{"type": "TextBlock","text": "${TITLE}"},{"type": "TextBlock","text": "${MESSAGE}"}]}}]}"

More info on the structure of an adaptive card : https://learn.microsoft.com/en-us/adaptive-cards/authoring-cards/getting-started More info on webhook json body structure : https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#example Adaptive Card designer : https://adaptivecards.io/designer/

Yes, it works.
What about "themeColor": "${COLOR}"? I tried adding this parameter, however, nothing happened.

@q2uantum
Copy link

q2uantum commented Jul 10, 2024

@whanklee You can add \"color\": \"<options>\"

are:

Default
Dark
Light
Accent
Good
Warning
Attention

@chusiang
Copy link
Author

chusiang commented Jul 12, 2024

@q2uantum Thank you for your share, I can send message to Chat via Workflows now, but I have no permission to send to Channel, so I can't verify it now.

I have put the script of teams-chat-post-for-workflows.sh .

[ chusiang@ubuntu-22.04 ~]
$ ./teams-chat-post-for-workflows.sh "https://prod-XXX.weXXXX.logic.azure.com:443/workflows/1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXf/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=BXXXXXXXXXF-fXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4" "Workflows" "Default" "Send from XXXXX-ubuntu."

2024-07-12-send-msg-to-teams-chat-via-workflows

@ronnyheymans
Copy link

@chusiang You have a typo in the script :
{ "type": "TextBlock", "text": "${MESSAGE}", "warp": true } should be
{ "type": "TextBlock", "text": "${MESSAGE}", "wrap": true }

@chusiang
Copy link
Author

chusiang commented Jul 12, 2024

@ronnyheymans Thank you for feedback, I have fixed it.

@zeyt27
Copy link

zeyt27 commented Jul 15, 2024

@chusiang thanks for your post, any idea how to get rid of the footnote message "... used a Workflow template to send this card. Get template" and to change the Workflow logo ?

@chusiang
Copy link
Author

chusiang commented Jul 16, 2024

Good news, I can send notification with teams-chat-post-for-workflows.sh to channel via workflows !

https://gist.github.com/chusiang/895f6406fbf9285c58ad0a3ace13d025?permalink_comment_id=5119162#gistcomment-5119162

2024-07-16-send-notification-to-channel-via-workflows

I guess, it's working now, because I am the owner role in this Teams.

Screenshot from 2024-07-16 18-53-35

@wengzy
Copy link

wengzy commented Jul 16, 2024

Thanks chusiang , is it possible remove the user name from message ?

@chusiang
Copy link
Author

Hi @wengzy , I think you need the title like "chusiang via Workflows", I can not see some options for it now.

https://adaptivecards.io/designer/

Screenshot from 2024-07-17 18-13-16

@lp-maximus
Copy link

I'm also successfully using your script to post, but my backend monitoring tool has checks against Windows drive pathing. When those checks pass their data to ${TITLE} or ${MESSAGE} it contains a \ in the drive path. This is breaking the JSON with a "Bad JSON escape sequence: \ . Path 'attachments[0].content.body[1].text" error. I've tried a couple of things to correct this issue, but haven't been able to get around it. Any thoughts?

@chusiang
Copy link
Author

chusiang commented Jul 22, 2024

Hi @lp-maximus,

I think we need add Escape Character for \ on L60 in teams-chat-post-for-workflows.sh.

https://gist.github.com/chusiang/895f6406fbf9285c58ad0a3ace13d025#file-teams-chat-post-for-workflows-sh-L60

I have also escape the \ char, maybe it can help you.

- MESSAGE=$(echo ${TEXT} | sed 's/"/\"/g' | sed "s/'/\'/g")
+ MESSAGE=$(echo ${TEXT} | sed "s/'/\'/g" | sed 's/"/\"/g; s/\\/\\\\/g')

Good luck.

Reference:

  1. Which characters need to be escaped when using Bash? | Stack Overflow
  2. How to use sed to find and replace text in files in Linux / Unix shell - nixCraft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment