Today’s post will cover the basics of using PowerShell to send Teams messages to users (One to One). This is through utilizing Microsoft Graph APIs.

Prerequisites

You need to download PowerShell Graph SDK from Microsoft PowerShell Gallery.

Required permission scope:

  • Chat.ReadWrite
  • Chat.Create

If you are new to Microsoft Graph, then you can read more about Microsoft Graph and the scope here Understanding Microsoft Graph SDK PowerShell.

To download the Password Expiery Notifier using Teams PS Script, you can download it from my GitHub, Also you can read more about it in my blog on Microsoft Community DevBlog Password Expiry Notification Using Teams and Graph API

Starting Teams Chat session using PowerShell.

Before sending a message to a Teams user using PowerShell, we must create the chat session to get a ChatID and then use the ChatId with each message sent.

Each chat session with a Teams user has its unique chat ID, so a chat session with UserA has a different ID when sending a chat message to UserB.

Please note that you cannot use application authentication to send a Teams chat message. If you use Get-MgChat or New-MgChatMessage, you gets the following error message:
Requested API is not supported in application-only context

To create the Teams chat using PowerShell session, you need to use the New-MgChat.

Using New-MgChat to Initiate a Chat Session

Graph Explorer is one of the best ways to start as it helps find information about the needed endpoint and permissions.

The Endpoint used to create chat is https://graph.microsoft.com/v1.0/chats

Graph Explorer

If you are not familiar with Microsoft Graph, I have already covered the basics you need to know in Using Graph Explorer To Find the Scope of a Cmdlet.

To start, we need to create a chat session using New-MgChat, then use the ID from New-MgChat to send messages. Please note that only one chat session can be created. If there was a previous chat session, then PowerShell returned that chat session ID.

You can use the Get-MgChat cmdlet to get a list of all the previous chats. Using the Get-MgChat, return a list of all previous chat sessions, including meetings and OneOnOne.

PS C:\Users\rescu> Get-MgChat

Id                                                                                          ChatType CreatedDateTime       LastUpdatedDateTime   TenantId                             Topic                            WebUrl
--                                                                                          -------- ---------------       -------------------   --------                             -----                            ------
19:19f3febd1-4e69-4e69-4e69-19f3febd16f6_febd16f6-4e69-4e69-4e69-19f3febd1@unq.gbl.spaces oneOnOne 20-Dec-20 10:02:59 AM 20-Dec-20 10:02:59 AM e55eec26-4d5a-4d5a-4d5a-e55eec26bf5a                                  https://teams.microsoft.com/l/chat/19%…
19:meeting_MTJhOWYzNGMtMDFhYS0MTJhOWYzNGMtOWYzNGMtMDFhYS@thread.v2                       meeting  20-Jun-22 10:18:24 AM 13-Jul-22 8:01:01 AM  e55eec26-4d5a-4d5a-4d5a-e55eec26bf5a New Meeting RFP                       https://teams.microsoft.com/l/chat/19%…

The New-MgChat requires some parameters defined in a collection of Hashtables and arrays. Feel free to copy it as is but just make sure to change the ID of the users in lines 11 and 18

To Get a user ID using Graph, you can use the Get-MgUser -Userid UserA@Domain.com

Import-Module Microsoft.Graph.Teams

$params = @{
	chatType = "oneOnOne"
	members = @(
		@{
			"@odata.type" = "#microsoft.graph.aadUserConversationMember"
			roles = @(
				"owner"
			)
			"user@odata.bind" = "https://graph.microsoft.com/v1.0/users('xxxxxxxx-xxxx-4xxd-xxxd-d72xxxxxxx1')"
		}
		@{
			"@odata.type" = "#microsoft.graph.aadUserConversationMember"
			roles = @(
				"owner"
			)
			"user@odata.bind" = "https://graph.microsoft.com/v1.0/users('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx')"
		}
	)
}

$myChatSession=New-MgChat -BodyParameter $params

Update 8 March 2024, I don’t know what did Microsoft do, but if you got the following error

The Param has the following values in its hashtable:

  • ChatType: Define the chat type. Is it one-to-one or a group? So the possible values are oneOnOne or Group.
  • Members: The type is an array. This array contains a hashtable of the possible members, including the member who initiated the chat session.
  • @odata.type: This is the type of a JSON object or name/value pair. Use the value as is.
  • Roles: all users are owners except for the guest. The possible values are Owner or Guest.
  • User@odata.bind is the URI for the user id participating in the chat. Replace the ID with the user’s ID, you can get this value by running. (get-mgUser -UserId test@mydomain.com).id

The New-MgChat uses the BodyParameter parameter and the $params as the argument to execute the operating

To see the result of the command, call the $myChatSession, the result looks like the following. We need the Id. The Id is assigned to New-MgChatMessage to send a message to a Teams user.

PS C:\Faris> $myChatSession | fl

ChatType             : oneOnOne
CreatedDateTime      : 20-Dec-20 10:02:59 AM
Id                   : 19:8ef78f89-b72e-b72e-b72e-19f3febd16f6_8ef78f89-b72e-433d-8287-19f3febd16f6@unq.gbl.spaces
InstalledApps        : 
LastUpdatedDateTime  : 20-Dec-20 10:02:59 AM
Members              : 
Messages             : 
OnlineMeetingInfo    : Microsoft.Graph.PowerShell.Models.MicrosoftGraphTeamworkOnlineMeetingInfo
Tabs                 : 
TenantId             : e55eec26-86c7-86c7-86c7-e55eec26bf5a
Topic                : 
WebUrl               : https://teams.microsoft.com/l/chat/19%19:8ef78f89-b72e-b72e-b72e-19f3febd16f6_8ef78f89-b72e-433d-8287-19f3febd16f6%40unq.gbl.spaces/0?te 
                       nantId=e55eec26-86c7-86c7-86c7-e55eec26bf5a
AdditionalProperties : {[@odata.context, https://graph.microsoft.com/v1.0/$metadata#chats/$entity]}

Send Teams Message Using PowerShell and New-MgChatMessage

As explained in the previous paragraph, we used the New-MgChat to get a chat Id. The Id includes information about all the participants in the chat.

To send a Teams message, we use the cmdlet New-MgChatMessage to send the message.

Explaining the New-MgChatMessage Parameter.

The New-MgChatMessage accepts many parameters, but in this post, I will focus on the main ones.

  • ChatId: is the chat id returned from the New-MgChat cmdlet.
  • Body: a hashtable contains the message content. It contains the following keys:
    • Content: the message you want to send. The type is a string.
    • ContentType: Message content type. Keep this key to HTML to send an HTML formatted message.
  • HostedContents: You can include pictures and other inline content to include in the chat message. The hosted content is an array of hashtable, each one should include the following:
    • “@microsoft.graph.temporaryId”: This is a temp ID. It can be whatever the value you want, but just make sure it matches with the Body
    • ContentBytes: It’s the binary string of the file you need to include. use the [System.IO.File]::ReadAllBytes('Path_To_Your_Image') to do the conversion.
    • ContentType: The type of the attached content. For example, “image/png”
  • Importance: Support three values Normal, High and Urgent.
  • Mentions: To mention a user in the sent message. The type of this object is an array of hashtables. Each hashtable is a single user and should include the following information.
    • ID: a serial number given to a user, start it from 0, and each added user to the mention should have a unique number.
    • MentionText: How the recipient sees his mention can be anything. For example, Mr. Faris Malaeb.
    • Mentioned: The list of entities that are part of the mention, the type of this object is a hashtable. The possible values are user, bot, team, channel, and tag. I will explain the User mention.
    • User: A hashtable of the user details which include:
      • ID: The ID of the user. Use Get-MgUser to find the user id.
      • UserIdentityType: the user directory location, usually, its aadUser.

Using New-MgChatMessage To Send Inline Image.

Some elements must be specified in the Body \ Content otherwise, the message won’t be delivered, and you will get an error.

Recall the HostedContent and how it has a unique ID, this ID must be passed inside the message Body \ Content.

– Dont forget, its an inline item not an attachment, so if you try to pass a PDF file it wont work and you will get an error about an unsupported content type.
New-MgChatMessage_CreateExpanded: Unsupported hosted content type
– I assume you already have the ChatID from Get-MgChat , and the value is stored in a $myChatSession.Id variable

See how the image from the HostedContents is presented in the Body in line 4. The img src presented as the following “../hostedContents/1/$value”. Keep it as is no need to change anything except the number “1”. So, in the following example, the temporaryId in the HostedContents is 1. All you need to do in the img src is use this number.. keep the rest the same.

$Body = @{
    ContentType = 'html'
    Content = @'
    <img height="200" src="../hostedContents/1/$value" width="200" style="vertical-align:bottom; width:700px; height:700px">
    <Strong>I am a nice bot</Strong>
'@
  }
  $HostedContents = @(
    @{
        "@microsoft.graph.temporaryId" = "1"
        ContentBytes = [System.IO.File]::ReadAllBytes("C:\Users\f.malaeb\Pictures\ShellBot.png")
        ContentType = "image/png"
    }
    )
  

New-MgChatMessage -ChatId $myChatSession.id -Body $Body -HostedContents $HostedContents

The result looks like this.

Send Message result.

Using New-MgChatMessage To Mention a User.

The following example sends an HTML message with a user named VDI One is mentioned.

See the Body \ Content how the mention is presented. You must use the following tag <at id="X">YYY YYY</at>. But you need to replace the X with the Id from the Mentions \ id.

Also, you need to replace the YYY YYY with the exact value from Mentions \ MentionText.

$Body = @{
    ContentType = 'html'
    Content = @'
     Hello Mr/Mis <at id="0">Mr. VDI One</at> and <at id="0">Mis. VDI Two</at><br> Thanks for your Message
'@
  }
$Mentions = @(
		@{
			Id = 0
			MentionText = "Mr. VDI One"
			Mentioned = @{
				User = @{
					Id = "5e65eafa-b164-b164-b164-5e65eafab164"
					UserIdentityType = "aadUser"
				}
			}
		}
	)

New-MgChatMessage -ChatId $myChatSession.id -Body $Body -Mentions $Mentions 

The results look like

Mentions

Sending Teams Chat Using PowerShell (Muiltiple Mentions and Inline Images)

The following example puts everything together and shows how to send multiple inline images with multiple mentions. This helps you understand how to add more and more elements to the chat message.

## Start a Chat Session using the New-MgChat to create a session ID
$params = @{
	ChatType = "oneOnOne"
	Members = @(
		@{
			"@odata.type" = "#microsoft.graph.aadUserConversationMember"
			Roles = @(
				"owner"
			)
			"User@odata.bind" = "https://graph.microsoft.com/v1.0/users('8f89cb19-6e65-6e65-6e65-8ef78f89cb19')"
		}
		@{
			"@odata.type" = "#microsoft.graph.aadUserConversationMember"
			Roles = @(
				"owner"
			)
			"User@odata.bind" = "https://graph.microsoft.com/v1.0/users('eafa16f6-b72e-b72e-b72e-5e65eafa16f6')"
		}
	)
}

$myChatSession=New-MgChat -BodyParameter $params

##### Sending Teams Message using New-MgChatMessage

$Body = @{
  ContentType = 'html'
  Content = @'
   Hello Mr/Mis <at id="0">Mr. VDI One</at> and <at id="1">Mis. VDI Two</at>
  <img height="200" src="../hostedContents/1/$value" width="200" style="vertical-align:bottom; width:700px; height:700px">
  <Strong>Thanks for your attention</Strong>
  <img height="200" src="../hostedContents/2/$value" width="200" style="vertical-align:bottom; width:700px; height:700px">
'@
}
$HostedContents = @(
  @{
      "@microsoft.graph.temporaryId" = "1"
      ContentBytes = [System.IO.File]::ReadAllBytes("C:\Users\f.malaeb\Pictures\ShellBot.png")
      ContentType = "image/png"
  }
  @{
    "@microsoft.graph.temporaryId" = "2"
    ContentBytes = [System.IO.File]::ReadAllBytes("C:\Users\f.malaeb\Pictures\Thanks.jpg")
    ContentType = "image/png"
}
)

$Mentions = @(
		@{
			Id = 0
			MentionText = "Mr. VDI One"
			Mentioned = @{
				User = @{
					Id = "5e65eafa-b164-b164-b164-5e65eafa16f6"
					UserIdentityType = "aadUser"
				}
			}
		}
        @{
			Id = 1
			MentionText = "Mis. VDI Two"
			Mentioned = @{
				User = @{
					Id = "53a804223-b535-b535-b535-60c7653a8047"
					UserIdentityType = "aadUser"
				}
			}
		}
	)

New-MgChatMessage -ChatId $myChatSession.id -Body $Body -HostedContents $HostedContents -Mentions $Mentions

The result looks like the following.

Thanks for your time 🙂

Related: Did you know you can also configure Azure AD conditional access using Microsoft Graph PowerShell module, Read more about it from here

Rate this post