<# .SYNOPSIS One-time setup for a council using Teams Notetaker. Run by a Teams + Exchange administrator. .DESCRIPTION 1. Teams: lets approved apps read meeting transcripts through Microsoft Graph, with speaker names. 2. Teams: creates an application access policy so Notetaker can read online meetings, transcripts and Copilot recaps - for the whole council or only for pilot users. 3. Exchange Online: lets Notetaker send ONLY as your sender mailbox (RBAC for Applications). Before running: approve Notetaker's permissions from the Notetaker admin page (that creates the "Teams Notetaker" enterprise application in your tenant). Requires PowerShell 7 with the MicrosoftTeams, ExchangeOnlineManagement and Microsoft.Graph.Applications modules (installed automatically if missing). .EXAMPLE ./setup-council.ps1 -SenderMailbox notetaker@yourcouncil.nsw.gov.au ./setup-council.ps1 -SenderMailbox notetaker@yourcouncil.vic.gov.au -PilotUsers jane@yourcouncil.vic.gov.au,sam@yourcouncil.vic.gov.au #> param( [string] $AppId = '6935260c-33cd-40fa-882a-a15d7b650926', [Parameter(Mandatory = $true)] [string] $SenderMailbox, [string[]] $PilotUsers = @(), [string] $PolicyName = 'Teams-Notetaker-Policy' ) $ErrorActionPreference = 'Stop' if ($AppId -notmatch '^[0-9a-fA-F-]{36}$') { throw 'Pass -AppId (the Notetaker application ID shown on the admin page).' } foreach ($module in 'MicrosoftTeams', 'ExchangeOnlineManagement', 'Microsoft.Graph.Applications') { if (-not (Get-Module -ListAvailable -Name $module)) { Write-Host "Installing $module..." -ForegroundColor Yellow Install-Module $module -Scope CurrentUser -Force } } # ------------------------------------------------------------ find the enterprise app Connect-MgGraph -Scopes 'Application.Read.All' -NoWelcome $sp = Get-MgServicePrincipal -Filter "appId eq '$AppId'" if (-not $sp) { throw 'Teams Notetaker is not in your tenant yet. Approve its permissions from the Notetaker admin page first.' } Write-Host "Found enterprise application: $($sp.DisplayName) ($($sp.Id))" # ------------------------------------------------------------ Teams Write-Host "`n== Microsoft Teams ==" -ForegroundColor Cyan Connect-MicrosoftTeams | Out-Null try { Set-CsTeamsMeetingConfiguration -Identity Global -EnableGraphTranscriptAccess $true -EnableAttributedTranscripts $true Write-Host 'Graph transcript access: ON (with speaker names)' } catch { Write-Warning "Could not change transcript API access here ($($_.Exception.Message))." Write-Warning 'Set it in Teams admin center > Meetings > Meeting settings > Transcript API access > Microsoft Graph access = On (and Include speaker attribution).' } if (-not (Get-CsApplicationAccessPolicy -Identity $PolicyName -ErrorAction SilentlyContinue)) { New-CsApplicationAccessPolicy -Identity $PolicyName -AppIds $AppId -Description 'Teams Notetaker' | Out-Null Write-Host "Created application access policy '$PolicyName'" } if ($PilotUsers.Count -gt 0) { foreach ($user in $PilotUsers) { Grant-CsApplicationAccessPolicy -PolicyName $PolicyName -Identity $user; Write-Host "Granted to $user" } Write-Host 'Also list these people as pilot organizers on the Notetaker admin page.' -ForegroundColor Yellow } else { Grant-CsApplicationAccessPolicy -PolicyName $PolicyName -Global Write-Host 'Granted to everyone in the council' } Write-Host 'Access policy changes can take up to 30 minutes.' -ForegroundColor Yellow # ------------------------------------------------------------ Exchange Write-Host "`n== Exchange Online ==" -ForegroundColor Cyan Connect-ExchangeOnline -ShowBanner:$false if (-not (Get-ServicePrincipal -Identity $AppId -ErrorAction SilentlyContinue)) { New-ServicePrincipal -AppId $AppId -ObjectId $sp.Id -DisplayName 'Teams Notetaker' | Out-Null } $scopeName = 'Teams Notetaker sender mailbox' if (-not (Get-ManagementScope -Identity $scopeName -ErrorAction SilentlyContinue)) { New-ManagementScope -Name $scopeName -RecipientRestrictionFilter "PrimarySmtpAddress -eq '$SenderMailbox'" | Out-Null } if (-not (Get-ManagementRoleAssignment -Role 'Application Mail.Send' -ErrorAction SilentlyContinue | Where-Object { $_.CustomResourceScope -eq $scopeName })) { New-ManagementRoleAssignment -App $AppId -Role 'Application Mail.Send' -CustomResourceScope $scopeName | Out-Null } Write-Host "Notetaker may send only as $SenderMailbox. Result of the check:" Test-ServicePrincipalAuthorization -Identity $AppId -Resource $SenderMailbox | Format-Table -AutoSize Write-Host "`nDone. Go back to the Notetaker admin page and select 'Run checks'." -ForegroundColor Green