GitHub Icon Image

List all external users in all site collections

Summary

This script helps you to list all external users in all SharePoint Online sites. It provides insights in who the users are, and if available who they where invited by.

  • CLI for Microsoft 365 with PowerShell
  • SPO Management Shell
  • PnP PowerShell
$fileExportPath = "<PUTYOURPATHHERE.csv>"

$m365Status = m365 status

if ($m365Status -match "Logged Out") {
  # Connection to Microsoft 365
  m365 login
}

$results = @()
Write-host "Retrieving all sites and check external users..."
$allSPOSites = m365 spo site classic list -o json | ConvertFrom-Json
$siteCount = $allSPOSites.Count

Write-Host "Processing $siteCount sites..."
#Loop through each site
$siteCounter = 0

foreach ($site in $allSPOSites) {
  $siteCounter++
  Write-Host "Processing $($site.Url)... ($siteCounter/$siteCount)"

  Write-host "Retrieving all external users ..."

  $users = m365 spo user list --webUrl $site.Url --output json --query "value[?contains(LoginName,'#ext#')]" | ConvertFrom-Json

  foreach ($user in $users) {
    $externalUserObject = m365 spo externaluser list --siteUrl $site.url -o json --query "[?AcceptedAs == '$($user.Email)']" | ConvertFrom-Json

    $results += [pscustomobject][ordered]@{
      UserPrincipalName = $user.UserPrincipalName
      Email             = $user.Email
      InvitedAs         = $externalUserObject.InvitedAs
      WhenCreated       = $externalUserObject.WhenCreated
      InvitedBy         = $externalUserObject.InvitedBy
      Url               = $site.Url
    }
  }
}

Write-Host "Exporting file to $fileExportPath..."
$results | Export-Csv -Path $fileExportPath -NoTypeInformation
Write-Host "Completed."

Check out the CLI for Microsoft 365 to learn more at: https://aka.ms/cli-m365


$fileExportPath = "<PUTYOURPATHHERE.csv>"

Connect-SPOService https://<yourorg>-admin.sharepoint.com

$results = @()
Write-host "Retrieving all sites and check external users..."
$allSPOSites = Get-SPOSite -Limit ALL
$siteCount = $allSPOSites.Count

Write-Host "Processing $siteCount sites..."
#Loop through each site
$siteCounter = 0

foreach ($site in $allSPOSites) {
  $siteCounter++
  Write-Host "Processing $($site.Url)... ($siteCounter/$siteCount)"

  Write-host "Retrieving all external users ..."

  $users = Get-SPOExternalUser -SiteUrl $($site.Url)

  Write-host "  $($users.Count) external users ..." -ForegroundColor Yellow

  foreach ($user in $users) {
    
    $results = [pscustomobject][ordered]@{
      DisplayName = $user.DisplayName
      Email       = $user.Email
      WhenCreated = $user.WhenCreated
      Url         = $site.Url
    }

    $results | Export-Csv -Path $fileExportPath -NoTypeInformation -Append
  }
}


Write-Host "Completed."

Check out the SPO Management Shell to learn more at: Introduction SharePoint Online Management Shell | Microsoft Docs


#Global Variable Declaration
$AdminURL = "https://domain-admin.sharepoint.com/"
$TenantURL = "https://domain.SharePoint.com"
$UserName = "chandani@domain.onmicrosoft.com"
$Password = "********"
$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force 
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
$DateTime = "_{0:MM_dd_yy}_{0:HH_mm_ss}" -f (Get-Date)
$BasePath = "E:\Contribution\PnP-Scripts\GetExtenalUsers\Logs\"
$CSVPath = $BasePath + "\ExternalUsers" + $DateTime + ".csv"
$global:ExternalUsersData = @() 
Function LoginToAdminSite() {
    [cmdletbinding()]
    param([parameter(Mandatory = $true, ValueFromPipeline = $true)] $Credentials)
    Write-Host "Connecting to Tenant Admin Site '$($AdminURL)'..." -ForegroundColor Yellow
    Connect-PnPOnline -Url $AdminURL -Credentials $Credentials
    Write-Host "Connection Successfull to Tenant Admin Site :'$($AdminURL)'" -ForegroundColor Green
}
Function ConnectToSPSite() {
    try {
        $SiteCollection = Get-PnPTenantSite -Filter "Url -like '$TenantURL'" | Where { $_.SharingCapability -ne "Disabled" }
        foreach ($Site in $SiteCollection) {
            $SiteUrl = $Site.Url    
            Write-Host "Connecting to Site :'$($SiteUrl)'..." -ForegroundColor Yellow  
            Connect-PnPOnline -Url $SiteUrl -Credentials $Credentials
            Write-Host "Connection Successfull to site: '$($SiteUrl)'" -ForegroundColor Green              
            GetExternalUsers($SiteUrl)                        
        }
        ExportData       
    }
    catch {
        Write-Host "Error in connecting to Site:'$($SiteUrl)'" $_.Exception.Message -ForegroundColor Red               
    } 
}
Function GetExternalUsers($siteUrl) {
    try {
        $ExternalUsers = Get-PnPUser | Where { $_.LoginName -like "*#ext#*" -or $_.LoginName -like "*urn:spo:guest*" }   
        Write-host "Found '$($ExternalUsers.count)' External users" -ForegroundColor Gray
        ForEach ($User in $ExternalUsers) {
            $global:ExternalUsersData += New-Object PSObject -Property ([ordered]@{
                    SiteName  = $site.Title
                    SiteURL   = $SiteUrl
                    UserName  = $User.Title
                    Email     = $User.Email
                    LoginName = $User.LoginName
                })
        }          
    }
    catch {
        Write-Host "Error in getting external users :'$($siteUrl)'" $_.Exception.Message -ForegroundColor Red                 
    }        
}

Function ExportData {
    Write-Host "Exporting to CSV" -ForegroundColor Yellow           
    $global:ExternalUsersData | Export-Csv -Path $CSVPath -NoTypeInformation -Append
    Write-Host "Exported Successfully!" -ForegroundColor Green 
}

Function StartProcessing {   
    LoginToAdminSite($AdminURL) 
    ConnectToSPSite
}

StartProcessing

Source Credit

Sample first appeared on List all external users in all site collections | CLI for Microsoft 365

Contributors

Author(s)
Albert-Jan Schot
Paul Bullock
Chandani Prajapati

Disclaimer

THESE SAMPLES ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

Back to top Script Samples
Generated by DocFX with Material UI