Post a #MicrosoftTeams channel chat message from #PowerShell using Graph API

Implementing Microsoft Teams is 10% IT, 10% governance and the rest is a cultural change. As part of the governance process, I have long seen the need to post the first chat message in a Team channel reminding the members of some cultural etiquette scenarios as part of a governance process. Up until now, December 2018, this was not possible unless you created an Incoming Webhook which required an administrator to log in to a Team which meant it was not something you could do during an automated creation.

Good news, you can now use the Graph API to post messages to channels without the webhook. This is still part of the beta API as of December 2018 and is not intended for production, yet. Here is what you need to do

Prerequisite: you need to create an Azure AD App registration with the correct permissions

  1. Log on to https://portal.azure.com with a GA administrator
  2. Navigate to Azure Active Directory
  3. go to App registration (Preview)
  4. Click + New registration
  5. Call it PowerShelltoTeamsGraphAPI
  6. Leave Redirect URI blank
  7. Go to Authentication and under Redirect URIs choose urn:ietf:wg:oauth:2.0:oob
  8. Click Save
  9. Go to API permissions to grant the required group read and write permissions
  10. Click + Add a permission
  11. Choose Microsoft Graph, Delegated permissions and choose Group.Read.All and ReadWrite.All (remember you need to expand Group)
  12. Click Grant admin Consent from  and click Yes
  13. You now have admin consent granted for your tenant
  14. Navigate to Overview
  15. Copy the Application (client) ID
  16. we are going to use it in the next step when logging on
  17. Check out the references pictures below

You are now ready to connect to the Graph API via PowerShell. The connection code is from a more thorough blog post by my MVP colleague Alexander Holmeset. $clientId is the client ID you copied in the prerequisites

#Connect Graph, use the client ID we created earlier in the lab called PowerShelltoTeamsGraphAPI in Azure AD under app registrations
#Source: https://alexholmeset.blog/2018/10/10/getting-started-with-graph-api-and-powershell/
$clientId = "bb808f16-b6ef-44aa-8218-2520aaff461e"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/common"
$AadModule = Import-Module -Name AzureADpreview -ErrorAction Stop -PassThru
$adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
# Get token by prompting login window.
$platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Always"
$authResult = $authContext.AcquireTokenAsync($resourceURI, $ClientID, $RedirectUri, $platformParameters)
$accessToken = $authResult.result.AccessToken

#Validate that you have access by getting a list of all Office 365 Groups in your tenant
$apiUrl = 'https://graph.microsoft.com/v1.0/Groups/'
$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $accessToken"} -Uri $apiUrl -Method Get
($Data | select-object Value).Value

Then you need to get the group ID and Id of the channel you want to post to. In this example, I use the Microsoft Teams PowerShell module and I want to post to a Team called TMDemo in the General channel. This can, of course, be done as part of a governance creation process

Connect-MicrosoftTeams

#I assume you only have one TMDemoXX Group
$TeamGroupID = (Get-Team | Where-Object {$_.displayname -match "TMDemo"}).GroupId
$TeamChannelID = (Get-TeamChannel -GroupId $TeamGroupID | Where-Object {$_.displayname -match "general"}).Id

Now you are ready to post to the channel, you are connected without errors, we have the Team you are posting to and have chosen a channel. There is one more thing, you also need to be a member of the Team in order to post. Make sure you get added, and then remove the admin user when you are finished posting. “content” is HTML text so you can format it nicely with bulletpoints and stuff.

#connect to teams channels and post a message
$apiUrl = "https://graph.microsoft.com/beta/teams/$TeamGroupID/channels/$TeamChannelID/chatThreads"
#add your admin user as member of the team
Add-TeamUser -User $UserName -GroupId $TeamGroupID
$body = @{
"rootMessage" = @{
    "body" = @{
        "contentType" = 1;
        "content" = '<h1>Welcome to this project. All project related discussions happen in the respective channels in our Team. We look forward to working with you and remember, General channel is used for announcements, wins and off-topic discussion</h1>'
        }
      }
}
$bodyJSON = $body | ConvertTo-Json
$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $accessToken"} -Uri $apiUrl -Method Post -Body $bodyJSON -ContentType 'application/json'
#remove your admin user from the team
Remove-TeamUser -User $UserName -GroupId $TeamGroupID

You have now successfully posted to a channel directly from PowerShell. Congratulations! Log in to your Team an see the result. I think this is great stuff and will definitely be part of my governance processes moving forward graph1