Deleting Channel Messages with the Microsoft Graph PowerShell SDK
A question in the Teams forum in the Microsoft Technical Community asks if it’s possible to clear out all the posts in a channel to “effectively start afresh.” Later in the thread, the reason is given that the channel is full of old messages relating to the COVID-19 pandemic and comments about working from home. The unwanted messages are in the General channel, so they’re obvious to all team members (unless they use the option to hide the General channel).
The suggested solution is to delete the channel. This is effective, especially as Microsoft now supports teams with up to 1,000 channels. In some cases, this is the right thing to do. In others, it can be painful to recreate all the channel tabs that existed in the deleted channel in a new channel.
In any case, the Teams clients don’t include an option for a team owner to remove all topics and replies from a channel, so the question is how to do the job. Deploying Microsoft 365 retention policies to remove items from channels once they reach a certain age could work, but retention policies won’t necessarily remove everything from a channel unless the retention period is set to be very short. In addition, you must wait for retention processing to complete and remove items from channels.
As is often the case, a potential answer lies in PowerShell. Specifically, by creating a script to find and remove channel messages using the cmdlets to interact with Teams data in the Microsoft Graph PowerShell SDK.
Sketching Out a Channel Cleanout Solution
On the surface, the steps involved in clearing out a team channel with PowerShell didn’t seem too complicated. Removing items from Teams channels is different from deleting Teams chat messages and the documentation for deleting a channel message specifies that application permissions are unavailable. The ChannelMessage.ReadWrite is only available with delegated permissions. The net effect is that only the message authors or a team owner can remove messages from a channel. That is if the team settings allow owners to delete messages. To remove all messages, the script must be run by a team owner.
Even so, the steps seem straightforward:
- Sign into the Microsoft Graph PowerShell SDK with the requisite permissions:
- ChannelMessage.ReadWrite: Remove messages.Team.ReadBasic.All: Read details of teams.TeamMember.Read.All; Read details of team members (to check that the signed-in user is a team owner).
- ChannelSettings.Read.All: Check the channel settings to make sure that owners can remove messages.
- Ask the user which team to target and then which channel to remove messages from.
- Check permissions to ensure the owner can remove messages.
- Fetch messages (topics) using the Get-MgTeamChannelMessage cmdlet.
- For each message, remove its replies with the Invoke-MgSoftTeamChannelMessageReplyDelete cmdlet.
- After removing replies, remove the base topic with the Invoke-MgSoftTeamChannelMessageDelete cmdlet.
- Keep processing until all messages are cleared out of the channel.
Initial tests with a prototype script proved that the approach was feasible. This extract gives an example of what the script did:
What team is the channel to clear out in?: Baden Workers Searching for the Baden Workers team Please select a channel from the following 1: Baden Private Discussions 2: General 3: Baden Shared Discussions 4: Goals 2020 Enter the number of the channel to select: 4 You selected channel number 4 - Goals 2020 Checking messages in the Goals 2020 channel... There are 8 messages in the Goals 2020 channel. Confirm removal of messages from Goals 2020 channel OK to go ahead and remove these messages? [Y] Yes [N] No [?] Help (default is "N"): y Removing messages... please wait All done - messages removed from channel
Slow Performance in Channel Message Retrieval
Then the script started to run into problems. The initial channels I tested against had a small number of topics. Then I tried with some channels that had been used as the target for a Twitter (X) connector (retired in 2020). The thing about the Twitter connector is that it could create many topics in a channel very quickly, depending on the activity of the Twitter accounts the connector monitored. Old Twitter messages don’t have a huge amount of value, so clearing them out from channels seemed like a very good thing to do.
Some of the teams in my tenant have channels with over 25,000 messages ingested through the Twitter connector (my only excuse is that I liked the Twitter connector and thought it was a great way to bring information into Teams). As I started testing the script against channels holding thousands of messages, it soon became obvious that the Get-MgTeamChannelMessage cmdlet is extraordinarily slow at retrieving messages.
I wanted to use the Get-MgTeamChannelMessageCount cmdlet to return the number of messages in a channel. Unfortunately, the cmdlet doesn’t work (bugged here). To find the number of messages that the script had to delete and to retrieve the details necessary to remove messages, the script therefore had to run the Get-MgTeamChannelMessage cmdlet.
The cmdlet works, but slowly. For instance, 36 minutes was needed to retrieve details of 3,516 messages, Compared to the retrieval speed for any other Microsoft 365 object, taking so long is excessive and unacceptable, so I filed another bug. I suspect that the problem lies in the Graph API that underpins the cmdlet because using the Graph List channel messages API was no faster when it came to retrieving objects. The problem might not affect Teams clients when they fetch message data from the Azure Cosmos DB message store because they minimize the amount of requested information by paging as users scroll through channel messages. It could also be the case that the Teams client uses a private API that doesn’t have the same performance characteristics as the Graph API.
No Effect on Retention or SharePoint Storage
It’s worth emphasizing that removing channel messages and replies does not affect the compliance records captured for Teams channels. The Microsoft 365 substrate captures these messages and keeps them for the duration of the retention period specified by the retention policies. Even though the script removes the channel messages and replies, the compliance records remain available for eDiscovery.
It’s also true that deleting messages from a Teams channel doesn’t remove items stored in SharePoint Online, like attachments or email messages sent to a channel. These items remain unaffected and intact.
Slow But Working Channel Message Removal Script
The script that I eventually ended up (downloadable from GitHub) with works but it’s slow. Not only is it slow to retrieve messages for a channel, but it’s also slow to remove messages and replies. For instance, the script took 68 minutes to remove 2,196 channel messages. However, the script does get the job done and clears things out to a point where the channel is devoid of messages (Figure 1).
![All channel messages are removed and the channel is ready for new activity.
Remove channel messages](https://s40823.pcdn.co/wp-content/uploads/2024/02/Clean-Out-Teams-Channel-No-Messages-1024x651.jpg)
I’ve run the script to clear out up to 20,000 messages from a channel. The extended periods necessary to find and remove messages are painful, but at least it’s a one-time operation. It’s always better when a computer performs repetitive boring actions, even slowly. Remember that the script demonstrates the principle of how a task can be achieved. It is not a fully-polished solution and you might need to make some changes and debug code to make it work in your tenant.
Let’s hope that Microsoft fixes the problems with the Graph SDK cmdlets to speed things up to the level that scripts can deal with other messages. Waiting for one-time operations to complete at a snail’s pace can remove some fun from life, and that’s always a pity.
The Real Person!
The Real Person!
Hi, awesome work, thanks.
You think it’s smart to had the capacity to choice a particular publisher ?
My example : I’m toto and i publish a lot of crap information, my IT department can delete all messages of TOTO in canal TUTU.
Thnaks for your reply 🙂
The Real Person!
The Real Person!
I think it is reasonable to clean out channels and remove posts from a specific source. I do this to remove old RSS feeds.
The Real Person!
The Real Person!
I added a comment on github, but when I removed the silentlycontinue command I got an error that the command needed ChannelMessage.Read.All API permissions as well. This helped.
The issue I see is that it doesn’t seemt to delete posts by UU (old users) and posts by Apps like Trello which are no longer in use.
The Real Person!
The Real Person!
Actually, the script looks for ChannelMessage.ReadWrite, which is one of the scope permissions listed. Maybe your session didn’t have this permission?
I’m not sure why the script can’t delete posts by unknown users or apps. That seems strange. But again, did your session have ChannelMessage.ReadWrite?
I also get
You selected channel number 1 – General
Checking messages in the General channel…
Removing messages… please wait
All done 0 messages and 1 replies removed from channel
i got:
You selected channel number 1 – General
Checking messages in the General channel…
Removing messages… please wait
All done 0 messages and 1 replies removed from channel
and the messages not deleted..!!
The Real Person!
The Real Person!
Maybe you didn’t have the permission to remove messages? Are you a team owner?
yes i am the Admin..
i even tried by using the teacher account himself…and got the same message…
note: i added a post using the Admin account, and the script deleted this post only successfully, but the teacher posts & students replies still not deleted…!
any hints plz
The Real Person!
The Real Person!
Ah, this is an Edu tenant… I don’t know anything about Edu tenants except that they can be different to commercial tenants. I don’t have access to an edu tenant so I can’t debug the issue.
This is an awesome little script. We have only had one request to clean up a channel conversation.Most times the old team is destroyed and a new one created.
I have tested it in our environment without issue so far and am modifying it accordingly to warn that all messages in the selected channel will be permanently deleted.