How to Bulk Assign Policies to Teams Users in Batch Jobs

Teams Bulk Policy Assignment to Large Numbers of Accounts Using Background Jobs

In yesterday’s post about disabling chat for Teams users, the conclusion was that assigning a messaging policy to users is the best approach. As explained in the post, it’s easy to create a policy. All the pain comes in assigning the policy to users, especially when this must be done for hundreds or even thousands of users.

Assigning a messaging policy to a single user is easy. Select the user in the Teams admin center, edit the policies assigned to their account, and make sure that the assigned messaging policy is the one which disables chat (Figure 1).

Assigning a no-chat messaging policy to a Teams user
Figure 1: Assigning a no-chat messaging policy to a Teams user

Using PowerShell to Assign a Messaging Policy

The same can be done with PowerShell using the Grant-CsTeamsMessagingPolicy cmdlet. This is loaded using the Skype for Business Online module (and soon, the Teams module). Here’s an example of assigning a messaging policy to a user:

Grant-CsTeamsMessagingPolicy -PolicyName "Restricted - No Chat" -Identity James.Joyce@office365itpros.com

Assigning Policies to Multiple Teams Users

The problem is how best to assign a policy to multiple Teams users. You could write a script to loop through a set of users and assign the policy with Grant-CsTeamsMessagingPolicy, but it’s easier to do this with a bulk (or batch) policy assignment, which runs a background job to assign a policy to multiple users.

Find the Target Users

The first thing to do is to determine the users we wish to assign the policy to. One way to approach the problem is to output a list of users to a CSV file, have someone edit the file to remove the accounts who should not be assigned the policy, and then use the edited CSV as the input for a bulk assignment of the messaging policy.

To create the CSV, run the Get-ExoMailbox cmdlet to fetch details of all mailboxes and then export the output to a CSV:

$Users = Get-ExoMailbox -RecipientTypeDetails UserMailbox | Select UserPrincipalName
$Users | Export-Csv -NoTypeInformation c:\temp\UsersToProcess.CSV

The CSV looks like the file shown in Figure 2. You should remove the entries for users who are not to be assigned the messaging policy and save the file.

Editing a CSV file to use as input for a Teams bulk policy assignment job
Figure 2: Editing a CSV file to use as input for a Teams bulk policy assignment job

Up to 5,000 accounts can be processed in a bulk policy assignment job, so if you have more than this number, you’ll need to split the accounts across several files.

Submit a Teams Bulk Policy Assignment Job

To submit the job, we read the CSV file data into a list variable and process it to extract just the user principal names, which is what’s expected as input for a bulk assignment job.

$TargetUsers = Import-CSV c:\temp\UsersToProcess.CSV
$PolicyUsers = [System.Collections.Generic.List[Object]]::new()
ForEach ($U in $TargetUsers) { $PolicyUsers.Add($U.UserPrincipalName) }

Then call the New-CsBatchPolicyAssignmentOperation cmdlet to associate the policy we want to assign with the set of target users. Make sure that you’re signed into PowerShell with an account that has the Teams administrator role or global administrator role. A successful submission results in a GUID to identify the batch job.

New-CsBatchPolicyAssignmentOperation -PolicyType TeamsMessagingPolicy -PolicyName "Restricted – No Chat” -Identity $PolicyUsers -OperationName "Teams Messaging Policy Assignment"
d9458f56-e03e-4f3d-9620-1d348547fb3b

We can use the GUID as input to the Get-CsBatchPolicyAssignmentOperation cmdlet to track the progress of the job:

Get-CsBatchPolicyAssignmentOperation -OperationId d9458f56-e03e-4f3d-9620-1d348547fb3b | Format-List

OperationId     : d9458f56-e03e-4f3d-9620-1d348547fb3b
OperationName   : Teams Messaging Policy Assignment
OverallStatus   : NotStarted
CreatedBy       : 53f08764-07d4-418c-8403-a737a8fac7b3
CreatedTime     : 07/07/2020 17:34:37
CompletedTime   :
CompletedCount  : 0

It is normal that a little while elapses before the batch processor begins working on a job. Eventually, the job will start, and the policy assignments will happen. You can then find out what was done by running a command to fetch the status of each user:

Get-CsBatchPolicyAssignmentOperation -OperationId d9458f56-e03e-4f3d-9620-1d348547fb3b | Select -ExpandProperty UserState

Id                                   Result                  State
--                                   ------                  -----
Imran.Khan@Office365itpros.com       Success                 Completed
Jeff.Guillet@office365itpros.com     Success                 Completed
Marc.Vigneau@office365itpros.com     Success                 Completed
Jane.Sixsmith@office365itpros.com    Unknown error occurred. Completed

The error reported might be due to the account already being assigned the policy. This is easily checked by viewing the account through the Teams admin center to see what policy is assigned.

The Value of Teams Bulk Policy Assignment

Assigning Teams policies in background jobs is most advantageous when you have thousands of accounts to manage. But even if you have just a few hundred, you’ll still find that it’s easier to kick off a background job than to write some PowerShell to assign a policy to a bunch of users.

For another example, see this post about how to assign a Teams update policy to users.


Struggling with the complexities of managing Microsoft Teams? Secure your copy of the Office 365 for IT Pros eBook and learn how to manage Teams effectively and efficiently.

12 Replies to “How to Bulk Assign Policies to Teams Users in Batch Jobs”

  1. Hello Tony!

    There seems to be a small error in the example script. In the New-CsBatchPolicyAssignmentOperation commandlet, you process $TargetUsers, that should be $PolicyUsers, no?

    I also wonder why you do it this way and not Import-CSV users.CSV | Select -ExpandProperty UserPrincipalName
    There is more than one ways to skin a cat and I am new to Powershell, so I am curious if there is a particular reason to go the explicit route for building the list.

    1. Hi Martin,

      You’re right. That was a cut and paste error on my part.

      I wrote the code like that because I like sticking data into hash tables. It must have been automatic on my part. In any case, the important thing is that you provide a simple list of UPNs as input for the job, no matter how you generate it.

  2. I take it there’s no way to cancel a Batch Policy Assignment yet? I’ve got an incorrect assignment in the activity log, that hasn’t started 4 hours later. I’d love to be able to cancel it but can’t find a way to.

  3. Hi there i’m afraid i havea different problem all together… I get “An error occurred on a send” whenever i try to run the batch commands, non batch commands work without issue, I am failing to see where the problem is. Does anyone have any experience with this?

    1. Does this happen all the time? Are you signed into PowerShell with an account that has Teams administrator permissions?

      1. Hi Toby yes, it’s all the time, I run the script using a group managed service account but when I make the connection to Microsoft teams I’m using a cloud only account with teams administrator permissions – for other o365 services I use the same set up and it works fine. Is teams working differently?

      2. Who’s Toby?

        In any case, are you saying that everything works OK when you run the command with one account and not when using a different one?

  4. Sorry Tony, auto correct, no I run my script as some account. if I connect to teams (by using my cloud only account which is a teams administrator) I am able to use commands like get-teamuser but the moment I try the batch assignments like in your examples, I receive an error that “an error occurred on a send” the error object contains no more information than this

    1. Time to call Microsoft support. They can run a remote session to see exactly what you are doing and might be able to see where the problem lies.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.