Table of Contents
Fix up the Teams Meeting Settings After Transferring the Exchange Event
In my article about how to use the Invoke-ChangeMeetingOrganizer cmdlet, I said that although the cmdlet can transfer ownership of a calendar event in an Exchange Online user mailbox, it utterly ignores the online component necessary for Teams meetings. Essentially, a Teams online meeting is in two parts: the calendar event in participant mailboxes, and an online space to which participants connect to join the meeting. The online space is pointed to by a join URL and the settings for the online space are maintained separately from the calendar event. These settings include the organizer, who can present, who can bypass the lobby, and so on.
Because the cmdlet ignores the online space and its settings, transferred calendar events are in an odd halfway state where the Exchange events are in the new organizer’s calendar, but the online spaces and settings point to the original meeting, including the old organizer. This can lead to the awkward situation where the new organizer cannot join the online event because they are not included in the list of the original participants.
More importantly, meeting recordings end up in the former organizer’s OneDrive for Business account and might be inaccessible to the new organizer. Even worse, because the former organizer’s OneDrive is probably unlicensed, all the data in the account might end up being deleted. All in all, it’s a mess.
I was surprised that Microsoft shipped the cmdlet without addressing the Teams component of transferred meetings. With more than 320 million Teams users generating millions of online meetings every day, it’s reasonable to assume that many online meetings need to be transferred when people leave an organization.
Fixing the Problem with PowerShell
After investigating the issue, I think I have a workaround based on Microsoft Graph APIs. Fortunately, I had some experience of creating and updating events, including online Teams events, from my work on the Automating Microsoft 365 with PowerShell eBook, and was able to code the solution as a PowerShell script based on the Microsoft Graph PowerShell SDK. You can download the script from the Microsoft 365 for IT Pros GitHub repository.
The script works on the assumption that meetings have already been transferred. In other words, the Exchange portion of the meeting events are in the new organizer’s calendar. The process which transferred the events (such as the script described in this article) should highlight the Teams meetings and create an input file containing details of the Teams meetings for the script to process. The input file contains sufficient information for the script to locate each transferred event in the new organizer’s calendar.
Application Permissions Used by the Script
The script uses the same Entra ID app as I used for the script to transfer meetings in bulk with one very important difference. The app must be assigned the Calendar.ReadWrite and OnlineMeetings.ReadWrite.All application permissions to allow it to update the calendar events (with the new meeting join information) and create new online meeting spaces. Use of the OnlineMeetings.ReadWrite.All permission also requires a Teams application access policy. You could consider this policy to be the equivalent of RBAC for applications for Teams data. A Teams application access policy dictates which Teams users an app is allowed to access data for. In this case, the Teams application policy is for the app which performs the update and it is granted to the account of the new meeting organizer. Here’s how I created the Teams application policy for the app:
New-CsApplicationAccessPolicy -Identity "Create Online Meetings via Apps" -AppIds "03ef5d75-e8dd-4f9e-a71c-fa81939d5ca2" -Description "This application access policy is assigned to user accounts to allow the nominated apps to create online meetings on their behalf."
And here’s how I assigned the policy to the target account:
Grant-CsApplicationAccessPolicy -PolicyName 'Create Online Meetings via Apps' -Identity 'ce0e26f8-da88-4efa-90ad-d16df1d9500d'
Remember to assign the application access policy to every account used to receive transferred meetings.
The Flow to Update Teams Meeting Settings
With the permissions in place, the script performed these steps:
- Read in the events to be updated.
- For each event, use the Get-MgUserDefaultCalendarEvent cmdlet to search the organizer’s calendar to find the event and its identifier, which is needed to update it later.
- If the event is found, run Update-MgUserEvent to remove the link with the original Teams meeting.
- Run the New-MgUserOnlineMeeting cmdlet to create a new online Teams meeting. A new meeting has a new meeting identifier and a new join URL. Participants will join this new meeting instead of the original online meeting. The old online meeting is no longer used (but can still be accessed, if necessary).
- After successfully creating an online meeting, use the Update-MgUserEvent cmdlet to write the details of the new Teams meeting into the event in the calendar.
Figure 1 shows a calendar event after it is updated with details of a new Teams meeting. The information for the online meeting is inserted into the body of the calendar event. The script code recreates the formatting used in regular Teams meeting notifications for the join URL, meeting identifier, and passcode. Other information can be extracted from the properties of the online meeting and inserted as HTML text if necessary.

Clicking the link starts the meeting as expected and everything works as expected, with the organizer of the Exchange meeting also now being the organizer of the Teams online event.
All the attendees for the calendar event can attend the Teams online meeting and can access artifacts like the meeting chat and transcript afterwards. The recording of the meeting ends up in the new organizer’s OneDrive for Business account. In short, it seemed like the Teams portion of the transfer had succeeded.
The Sand in the Works
Detail tends to get in the way of software implementations. In this case, I noticed that the calendar events included join information for a different Teams meeting so that information for two online meetings were in the body of the transferred events (Figure 2). The online meeting created by the script is at the top of the message body.

The reason why the second meeting exists is that the request body to update the meeting included settings to say that the event is an online Teams meeting (isOnlineMeeting is true and onlineMeetingProvider is teamsForBusiness). When the cmdlet ran to update the meeting with the information about the online event we created, it noticed that these properties are present and if the calendar event isn’t currently marked as a Teams meeting, the cmdlet creates a new online meeting and adds its details to the message body.
$EventDetails = @{}
$EventDetails.Add("isOnlineMeeting", $true)
$EventDetails.Add("body", $EventBody)
$EventDetails.Add("onlineMeetingProvider", "teamsForBusiness")
The documentation for the create online meeting API warns that the API creates a standalone online meeting that isn’t associated with a calendar event and recommends that the Create Event API is used to create an online meeting backed up with a calendar event. That’s absolutely the correct course when creating an online meeting from scratch but didn’t seem to be appropriate in this scenario when the calendar event already existed.
The only way to suppress the second online event is not to set the two properties. This has the downside of marking the calendar event as not being an online Teams meeting, which means that when the calendar displays the notification for the meeting, a join button isn’t shown.
I think the join button is a valuable feature, so I resorted to a quick fix by updating the body content of the calendar event to remove any mention of other Teams meetings. It’s a hack, but all we’re doing here is experimenting to prove a concept, so it’s acceptable, even if the calendar (Exchange and Teams) don’t treat the event as a Teams online meeting.
Microsoft Could Do Better
This was an interesting challenge because it exposed the disconnect between the Exchange and Teams components of online meetings. Once you understand that separation, the fix is relatively straightforward. Or so it seems until you more thoroughly investigate what’s possible with the available public APIs.
The script is not perfect and there’s lots that it doesn’t do, including dealing with attachments, text, Loop components, and so on that might associated with meetings. All these entities can be processed for transferred meetings. It’s just a matter of code.
What the script does is demonstrate the feasibility of adjusting the Teams online meetings associated with transferred calendar events. With access to internal APIs, Microsoft could do a better job to make sure that everything associated with the original online event is moved, including an online meeting organized by the user who accepts the transferred event and make sure that the transferred event is treated as a Teams online meeting. This raises the question of why Microsoft did not address the Teams issue when it introduced the Invoke-ChangeMeetingOrganizer cmdlet. It is a major oversight which means that the cmdlet is, for now, terribly flawed.
Support the work of the Microsoft 365 for IT Pros team by subscribing to the Microsoft 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365. Only humans contribute to our work!
Re the “Run the New-MgUserOnlineMeeting cmdlet to create a new online Teams meeting” section of the workflow, doesnt this need to send an update to the participants given that the meeting URL will be changing, else their original invites will be invalid? I might have misunderstood that part but interested to know what the experience is like for the user who received the original invite prior to the change. Thanks Tony.
Yep. The meeting participants receive an updated meeting request containing the details of the new Teams online event. In most cases, Outlook processes the request silently and updates the user calendars without people realizing what happened.