Office 365

Mentioning users in notifications using PSTeams PowerShell Module

Microsoft Teams over the last few years have grown into an excellent and flexible tool for both small and big companies. Having the ability to chat with users, store files or have all sorts of data in one place makes it easy and functional. Of course, it has its fair share of issues, but it's getting better. One of the cool features of Microsoft Teams is being able to send notifications to Microsoft Teams Channels using WebHook Notifications. In the beginning, this feature was pretty limited, but after a few years, it got much better with support for Adaptive Cards, List Cards, Hero Cards, Thumbnail Cards, and Office 365 Connector Card.

Sending notifications to Microsoft Teams

Sending notifications to Microsoft Teams using PowerShell is pretty straightforward – use Invoke-WebRequest and prepare proper JSON structure, and you're done!

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "size": "Medium",
      "weight": "Bolder",
      "text": "${title}",
      "wrap": true,
      "style": "heading"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "items": [
            {
              "type": "Image",
              "style": "Person",
              "url": "${creator.profileImage}",
              "size": "Small"
            }
          ],
          "width": "auto"
        },
        {
          "type": "Column",
          "items": [
            {
              "type": "TextBlock",
              "weight": "Bolder",
              "text": "${creator.name}",
              "wrap": true
            },
            {
              "type": "TextBlock",
              "spacing": "None",
              "text": "Created {{DATE(${string(createdUtc)}, SHORT)}}",
              "isSubtle": true,
              "wrap": true
            }
          ],
          "width": "stretch"
        }
      ]
    },
    {
      "type": "TextBlock",
      "text": "${description}",
      "wrap": true
    },
    {
      "type": "FactSet",
      "facts": [
        {
          "$data": "${properties}",
          "title": "${key}:",
          "value": "${value}"
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.ShowCard",
      "title": "Set due date",
      "card": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "Input.Date",
            "id": "dueDate"
          },
          {
            "type": "Input.Text",
            "id": "comment",
            "placeholder": "Add a comment",
            "isMultiline": true
          }
        ],
        "actions": [
          {
            "type": "Action.Submit",
            "title": "OK"
          }
        ],
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
      }
    },
    {
      "type": "Action.OpenUrl",
      "title": "View",
      "url": "${viewUrl}"
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.0"
}

Well, maybe not that easy. Fortunately, it's pretty easy with the help of the PSTeams PowerShell Module that I wrote. If you've never heard of it, you can find out more in those blog posts where I describe how you can take that pain away and just create something in minutes.

Small reminder on how PSTeams 2.0 makes it easy to send notifications

PSTeams 2.0 added a lot of new options to create notifications using Adaptive Cards. It's very flexible and allows to create even complicated cards with lots of information.

New-AdaptiveCard -Uri $Uri {
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text 'Publish Adaptive Card schema' -Weight Bolder -Size Medium
        New-AdaptiveColumnSet {
            New-AdaptiveColumn -Width auto {
                New-AdaptiveImage -Url "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg" -Size Small -Style person
            }
            New-AdaptiveColumn -Width stretch {
                New-AdaptiveTextBlock -Text "Matt Hidinger" -Weight Bolder -Wrap
                New-AdaptiveTextBlock -Text "Created {{DATE(2017-02-14T06:08:39Z, SHORT)}}" -Subtle -Spacing None -Wrap
            }
        }
    }
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text "Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation." -Wrap
        New-AdaptiveFactSet {
            New-AdaptiveFact -Title 'Board:' -Value 'Adaptive Card'
            New-AdaptiveFact -Title 'List:' -Value 'Backlog'
            New-AdaptiveFact -Title 'Assigned to:' -Value 'Matt Hidinger'
            New-AdaptiveFact -Title 'Due date:' -Value 'Not set'
        }
    }
}

With just a few lines of PowerShell, that are descriptive and more or less self-explaining we got a nicely formatted Adaptive card. PSTeams module generated full JSON for you without bugging you about it.

{
    "type": "message",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "content": {
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "type": "AdaptiveCard",
                "version": "1.2",
                "body": [
                    {
                        "type": "Container",
                        "items": [
                            {
                                "type": "TextBlock",
                                "text": "Publish Adaptive Card schema",
                                "size": "Medium",
                                "weight": "Bolder"
                            },
                            {
                                "type": "ColumnSet",
                                "columns": [
                                    {
                                        "type": "Column",
                                        "width": "auto",
                                        "items": [
                                            {
                                                "type": "Image",
                                                "url": "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg",
                                                "size": "Small",
                                                "style": "person"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "Column",
                                        "width": "stretch",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Matt Hidinger",
                                                "weight": "Bolder",
                                                "wrap": true
                                            },
                                            {
                                                "type": "TextBlock",
                                                "text": "Created {{DATE(2017-02-14T06:08:39Z, SHORT)}}",
                                                "spacing": "None",
                                                "wrap": true,
                                                "isSubtle": true
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "type": "Container",
                        "items": [
                            {
                                "type": "TextBlock",
                                "text": "Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation.",
                                "wrap": true
                            },
                            {
                                "type": "FactSet",
                                "facts": [
                                    {
                                        "title": "Board:",
                                        "value": "Adaptive Card"
                                    },
                                    {
                                        "title": "List:",
                                        "value": "Backlog"
                                    },
                                    {
                                        "title": "Assigned to:",
                                        "value": "Matt Hidinger"
                                    },
                                    {
                                        "title": "Due date:",
                                        "value": "Not set"
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        }
    ]
}
FullWidth and Mentioning in PSTeams 2.1.0

In this blog post, I wanted to show you a couple of new features that were added after PSTeams 2.0.

We added a FullWidth switch to New-AdaptiveCard, making your card fit available space.

With just a single parameter you can now make your Adaptive Card fill in all available space.

New-AdaptiveCard -Uri $Uri {
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text 'Publish Adaptive Card schema' -Weight Bolder -Size Medium
        New-AdaptiveColumnSet {
            New-AdaptiveColumn -Width auto {
                New-AdaptiveImage -Url "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg" -Size Small -Style person
            }
            New-AdaptiveColumn -Width stretch {
                New-AdaptiveTextBlock -Text "Matt Hidinger" -Weight Bolder -Wrap
                New-AdaptiveTextBlock -Text "Created {{DATE(2017-02-14T06:08:39Z, SHORT)}}" -Subtle -Spacing None -Wrap
            }
        }
    }
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text "Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation." -Wrap
        New-AdaptiveFactSet {
            New-AdaptiveFact -Title 'Board:' -Value 'Adaptive Card'
            New-AdaptiveFact -Title 'List:' -Value 'Backlog'
            New-AdaptiveFact -Title 'Assigned to:' -Value 'Matt Hidinger'
            New-AdaptiveFact -Title 'Due date:' -Value 'Not set'
        }
    }
} -FullWidth
We are now able to use mentions in the Adaptive Cards meaning it's now possible to notify specific team members about an issue

New-AdaptiveCard -Uri $Uri {
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text 'Publish Adaptive Card schema' -Weight Bolder -Size Medium
        New-AdaptiveColumnSet {
            New-AdaptiveColumn -Width auto {
                New-AdaptiveImage -Url "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg" -Size Small -Style person
            }
            New-AdaptiveColumn -Width stretch {
                New-AdaptiveTextBlock -Text "Przemysław Kłys <at>Przemysław Kłys</at>" -Weight Bolder -Wrap
                New-AdaptiveTextBlock -Text "Created {{DATE(2017-02-14T06:08:39Z, SHORT)}}" -Subtle -Spacing None -Wrap
            }
        }
    }
    New-AdaptiveContainer {
        New-AdaptiveTextBlock -Text "Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation." -Wrap
        New-AdaptiveFactSet {
            New-AdaptiveFact -Title 'Board:' -Value 'Adaptive Card'
            New-AdaptiveFact -Title 'List:' -Value 'Backlog'
            New-AdaptiveFact -Title 'Assigned to:' -Value 'Matt Hidinger'
            New-AdaptiveFact -Title 'Due date:' -Value 'Not set'
        }
    }
    # we need to tell PSTeams to match <at> tags to the user's profile using UPN or AAD ID
    New-AdaptiveMention -Text 'Przemysław Kłys' -UserPrincipalName 'przemyslaw.klys@domain.pl'
} -FullWidth

What is weird and seems like a Microsoft Teams bug is that the <at> tags are not appropriately replaced and require you to provide both a text (any text) and text to display if you want to maintain both. However, if you give the wrong UserPrincipalName (non-existing user), the Microsoft Teams will behave correctly and act like it mentions users manually.

We have to wait for Microsoft to see if they fix it. This feature started to work just recently, so there's room for improvement. I hope that those two new features will make you more productive and use Teams notifications even more!

PSTeams - How to get it up and running?

How do you install it? The easiest and most optimal way is to use PowerShellGallery. This will get you up and running in no time. Whenever there is an update, just run Update-Module, and you're done.

Install-Module PSTeams
# Update-Module PSTeams

However, if you're into code – want to see how everything is done, you can use GitHub sources. Please keep in mind that the PowerShellGallery version is optimized and better for production use. If you see any issues, bugs, or features that are missing, please make sure to submit them on GitHub.

This post was last modified on %s = human-readable time difference 20:34

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

1 month ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

2 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

7 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

11 months ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago