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}"
@ehouston3
Copy link

Additionally, if you create the workflow without using a template, the footer advertisement for templates won’t be present. I think it’s there to promote the use of workflow templates to save time. You can assemble the same components that are in the template and not have to worry about the footer advertisement.

@chusiang
Copy link
Author

chusiang commented Jul 25, 2024

Thanks for feedback from @cowbe0x004 and @ehouston3 ,
I have tried to remove the footer, but something is working and something not.

2024-08-01-ms-teams-workflows-notification-no-footer

If we want to stop show (or remove) the footer:

  1. Manual create the workflows, not from template. #gistcomment-5131921
  2. Clone the working one from template, and use the new one. #gistcomment-5131697

I think the answer is clean now.

CC @zeyt27

@jymchng
Copy link

jymchng commented Aug 5, 2024

This is beautiful. Thank you!

@whanklee
Copy link

How to send a message on Microsoft teams with new line character? With \n not working. What should I use?

@chusiang
Copy link
Author

Hi @whanklee , please try \n\n, it's working on https://adaptivecards.io/designer .

{
  "type": "TextBlock",
  "text": "It doesn't wrap by\n\n default",
  "weight": "bolder"
},

@whanklee
Copy link

Hi @chusiang,
\r\n\r\n works well.

@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