How to Send a Microsoft Teams Message using PowerShell 7

Microsoft Teams is up and coming in the world of business chat and collaboration clients. Much like Slack, Microsoft Teams offers many of the same tools and integration abilities. A key selling point of business-oriented chat clients is the interoperability that the clients offer. This interoperability allows organizations to increasingly move their processes to different mediums, such as a chat client.

Of course, to actually integrate those abilities into a client such as Microsoft Teams, it’s necessary to use a programming and automation language to do so. One such language, that fits very well into the Microsoft ecosystem, is PowerShell 7. Easily able to interact with web REST APIs, which Microsoft Teams offers, PowerShell makes it simple to create and send messages into a given Teams channel.

Microsoft Teams API

Two different methods of interacting with Microsoft Teams exist, bots and webhooks. As it is much more complicated to set up a bot than a webhook, this article will focus on the latter method. There are two steps to connecting PowerShell and Microsoft Teams.

Create Incoming Webhook

Incoming webhooks are scoped to the channel level. Each webhook connector is unique to the channel that it is created. This allows for a more secure and better-controlled environment as any client that can send in an HTTPS POST requests and has the correct URL is able to send a message.

For anyone that is creating a webhook connector will need the appropriate permissions. These are Team Settings → Member Permissions → Allow Members to Create, Update, and Remove Connectors.

  1. Navigate to the channel where you want to add the webhook and select More Options
  1. Choose Connectors from the drop-down menu and find Incoming Webhook
  1. Select the Configure button and provide a name for the webhook
  1. Copy the unique URL displayed in the dialog box
  1. Click on Done to finalize creating the webhook
?
One important note about webhooks, they do not support adaptive cards, unlike many other Microsoft services. You can create actionable cards, but not using the adaptive card layout.

PowerShell 7 Message Code

Often, a simple alert message is all that is needed. In this case, the most common and simple parameters to use are below.

  • summary
  • themeColor
  • title
  • text

The @type and @context are to tell Microsoft Teams what kind of message is coming in and what schema to use to decode and post the message.

$JSONBody = [PSCustomObject][Ordered]@{
    "@type"      = "MessageCard"
    "@context"   = "http://schema.org/extensions"
    "summary"    = "Incoming Alert Test Message!"
    "themeColor" = '0078D7'
    "title"      = "Incoming Alert Test Message!"
    "text"       = "There was an alert and we should act on it."
}

$TeamMessageBody = ConvertTo-Json $JSONBody -Depth 100

$parameters = @{
    "URI"         = 'https://outlook.office.com/webhook/{GUID}@{GUID}/IncomingWebhook/{GUID}/{GUID}'
    "Method"      = 'POST'
    "Body"        = $TeamMessageBody
    "ContentType" = 'application/json'
}

Invoke-RestMethod @paramete
rs | Out-Null
?
The {GUID} within the URI are just placeholders as the real generated URI is very long and will contain multiple unique GUID values.

After sending in the above code, you will get a similar result within the Microsoft Teams client.

Untitled 13

Extending the PowerShell Message

Now that we have sent in a simple message, how do we create something that is a bit more useful, such as adding an image and an action link or split the text into different sections? Thankfully, the schema does allow us to add some of these additional features to our messages. These features often make the difference between an actionable message and one that may be passed over.

Sections

Messages can be split up into different sections to group information and using the facts construct allows you to display information in an easier to digest format.

$JSONBody = [PSCustomObject][Ordered]@{
    "@type"      = "MessageCard"
    "@context"   = "http://schema.org/extensions"
    "summary"    = "Incoming Alert Message!"
    "themeColor" = '0078D7'
    "sections"   = @(
		    @{
					"activityTitle"    = "Alert Section"
          "activitySubtitle" = "Alert SubSection"
          "facts"            = @(
						@{
							"name"  = "Name1"
							"value" = "Value1"
						},
						@{
							"name"  = "Name2"
							"value" = "Value2"
						}
					)
					"markdown" = $true
				}
    )
}

As you can see from the message below, this is already looking a lot better. Next, we will add an action link and an image to the message.

Untitled 14

Images and Markdown

By using an activityImage we can set up an image to display and change that based on context. This is great to put in images that provide at-a-glance information such as a warning image. This could also be used to display graphs of problems that have occurred.

$JSONBody = [PSCustomObject][Ordered]@{
  "@type"      = "MessageCard"
  "@context"   = "http://schema.org/extensions"
  "summary"    = "Incoming Alert Message!"
  "themeColor" = '0078D7'
  "sections"   = @(
	    @{
				"activityTitle"    = "Alert *Section*: _Testing_"
        "activitySubtitle" = "Alert SubSection"
				"activityImage"    = "https://myalertsystem.com/warning.png"
        "facts"            = @(
					@{
						"name"  = "Name1"
						"value" = "Value1"
					},
					@{
						"name"  = "Name2"
						"value" = "Value2"
					}
				)
				"markdown" = $true
			}
  )
}

As you can see, the Alert Section is formatted using Markdown. This allows for rich markup that you can use to make the messages easier to digest and understand. Markdown that is available for use with the messages is.

  • *Italic*
  • **Bold**
  • ***Bold Italic***
  • ~~Strike-through~~
  • # Heading through ###### Heading
  • * List Item or – List Item

Untitled 15

Actions

Finally, there are a handful of action types that you can add to your messages. These allow you to add buttons to open a URL or collect input and POST back to a URL. These can be very useful to let you create simple workflow cards within the Teams client without needing to create a bot for more complex workflows.

Conclusion

Though Microsoft Teams may not be quite as well-established as Slack is, it is quickly becoming a valuable addition to many organizations. With the free edition available to anyone as well, it’s a low-cost solution for most small organizations looking to get started with an integrated chat client.

Utilizing PowerShell and Microsoft Teams makes for a powerful combination. Many organizations are moving to operations that can be conducted in a collaborative environment such as a chat application. With the integration of other systems and processes into this application, Microsoft Teams allows you to quickly expand the productivity and abilities of your workforce to receive and act upon information!