Skip to content

Instantly share code, notes, and snippets.

@chusiang
Last active April 28, 2025 01:31
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 color specified."
exit 1
fi
shift
# Text.
TEXT=$*
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}"
@alaxelmck
Copy link

alaxelmck commented Sep 18, 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

Hi,

In my case I'm passing to the script an output of another script, which takes sql query result and concats with another line having an escaped newline:
query-db-and-pass-to-teams-script.sh
MESSAGE="$SQL_RESULT" # Which is a 5 line string, 1st 4 ending with literal newlines.
MESSAGE+="\nAnother line here"
${TEAMS_SCRIPT} "$WEBHOOK_URL" "$TITLE" "$COLOR" "$MESSAGE"

So when this $MESSAGE is passed to your script, several issues occur at this line:
MESSAGE=$(echo ${TEXT} | sed "s/'/\'/g" | sed 's/"/\"/g; s/\\/\\\\/g')

  1. If we use echo ${TEXT} - it will eat all literal newlines. Had to use echo "${TEXT}" to avoid that.
  2. s/\/\\/g turns my concated escaped newline in "\nAnother line here" into "\\\\nAnother line here"

P.S.
echo "No status specified."
Was it meant "No color specified."?

@chusiang
Copy link
Author

chusiang commented Sep 19, 2024

Hi @alaxelmck,

I have update to No color specified., it's typo with I copy from my old script like slack-chat-post.sh .

About support output of another script part, I have no idea now.

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