Entra / Microsoft 365 · Users & guests
Analyze external calendar meetings
Find out what external domains users who attend meetings belong to.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -AppId $AppId -TenantId $TenantId -CertificateThumbprint $Thumbprint -NoWelcome
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([string] $TenantId = "",[string] $AppId = "",[int] $LookbackDays = 365,[string] $StartDate = (Get-Date).AddDays(-$LookbackDays),[string] $EndDate = (Get-Date).AddDays(1))$Thumbprint = '6FBD36F588E12DE291100371E16219863E399818'# Permissions used# User.Read.All - Read user account information, including licenses.# Group.Read.All - Read test group info.# GroupMember.Read.All - Read members of the test group# Calendars.Read - Read user calendars# Domain.Read.All - Read accepted domains defined for the tenantConnect-MgGraph -AppId $AppId -TenantId $TenantId -CertificateThumbprint $Thumbprint -NoWelcomeClear-Host# Define the GUID for the Teams service plan$TeamsServicePlanId = '57ff2da0-773e-42df-b2af-ffb7a2317929'# Define the name of an Entra ID group whose members are used to test the script (or run the script for a subset of users)$GroupName = "Test Users for Graph Scripts"# See if the test group exists containing the user accounts for testing. If not, find all user accounts licensed with a Teams service planWrite-Host "Finding user accounts to analyze..."Try {$Group = Get-MgGroup -Filter "displayName eq '$GroupName'" -ErrorAction Stop$GroupMembers = Get-MgGroupMember -Group $Group.Id[array]$Users = $GroupMembers | Select-Object -ExpandProperty Id} Catch {[array]$Users = Get-MgUser -Filter "assignedPlans/any(c:c/servicePlanId eq $TeamsServicePlanId and capabilityStatus eq 'Enabled')" `-ConsistencyLevel eventual -CountVariable Test -All -PageSize 500 | Select-Object -ExpandProperty Id}If ($Users.Count -eq 0) {Write-Host "No users found in the group or with the Teams service plan. Exiting script."Break} Else {Write-Host ("Found {0} users to analyze" -f $Users.Count)}# Get the domains defined for the tenantWrite-Host ("Finding domains defined for tenant {0}" -f $TenantId)[array]$Domains = Get-MgDomain -All | Select-Object -ExpandProperty Id | Sort-Object# Start and end dates for the reporting period$CalendarInfo = [System.Collections.Generic.List[Object]]::new()[array]$DomainsFound = $nullForEach ($User in $Users) {Write-Host "Processing calendar for $User"[array]$CalendarData = Get-MgUserCalendarView -UserId $User -StartDateTime $StartDate -EndDateTime $EndDate -All -PageSize 250# Drop cancelled events and filter to get online meetings - if you want to exclude private events from the set, use Where-Object {$_.sensitivity -ne "private"}$CalendarData = $CalendarData | Where-Object {$_.isCancelled -eq $False -and $_.isOnlineMeeting -eq $True}If ($CalendarData) {Write-Host ("Found {0} online meetings for {1}" -f $CalendarData.Count, $User)} Else {Continue}[array]$UserDomainsFound = $null# Extract attendees and find what domains they come fromForEach ($CalendarEvent in $CalendarData) {# Check if the meeting organizer is from our tenant. If not, the event is organized elsewhere and we ignore it$Organizer = $CalendarEvent.organizer.emailaddressIf ($Organizer.address.Split("@")[1] -notin $Domains) {Continue}# Get the set of attendees and extract the domains for attendees not in our tenant[array]$EventAttendees = $CalendarEvent.attendees.emailaddressIf ($EventAttendees) {ForEach ($Attendee in $EventAttendees) {$AttendeeDomain = $Attendee.Address.Split('@')[1]If ($AttendeeDomain -notin $Domains) {$UserDomainsFound += $AttendeeDomain}}}}$DomainsFound = $DomainsFound + $UserDomainsFound$ReportLine = [PSCustomObject]@{User = $UserMeetingCount = $CalendarData.CountExternalDomains = ($UserDomainsFound | Sort-Object -Unique) -join "; "}$CalendarInfo.Add($ReportLine)}[array]$UniqueDomains = $DomainsFound | Sort-Object -UniqueWrite-Host ""Write-Host "All done... Unique domains found" ($UniqueDomains -join "; ")
Parameters
ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.-AppId""Application (client) ID for the app registration used to connect.-LookbackDays365How many days back to scan user calendar events.-StartDate(Get-Date).AddDays(-365)Start of the reporting window.-EndDate(Get-Date).AddDays(1)End of the reporting window.Attribution
Author
Office365itpros