Saturday, April 6, 2019

Microsoft Teams Report for Office 365 Tenant

This requirement came from our management to extract the Teams report across our tenant.

Fortunately in the latest team module released by Microsoft, you can extract all the Teams across the Tenant and its not like the older module where you can get only the Teams you own.

Here is the requirement:

  • All Teams across the Tenant

  • It should show if Team is public or private, Name, Sharepoint Url

  • Show Count Public and Private (Total count)




Extract the below script and run in Powershell as shown below.

https://gallery.technet.microsoft.com/scriptcenter/Teams-Report-for-Office-2e7a7b82

or you can get this Script from PowerShell gallery (Install-Script -Name TeamsReport)

https://www.powershellgallery.com/packages/TeamsReport

Change below parameters under logs and variables

$smtpserver = "SMTPserver"

$from = "donotreply@labtest.com"

$erroremail = "Reports@labtest.com"

 



Below are the prerequisites to run this script as all the above requirements for the report can not be fulfilled just by using Teams module, we need to extract some stuff from the office 365 group object or you can say Exchange unified group.

  • Latest team module


Install-Module -Name MicrosoftTeams -RequiredVersion 0.9.5

https://www.powershellgallery.com/packages/MicrosoftTeams/0.9.5

  • Exchange Online Shell


Script will first connect to teams to extract all the Teams in the tenant and than all unified groups from Exchange online.

Ones these are fetched, these are compared to each other via groupid as anchor to extract the report as needed.

Logs and report folder are created if these do not exist, for storing log and html report.

HTML report will not only be saved under the report folder but is sent via email.



Logs and report retention is set to 60 days and can be changed by editing the limit value towards the end of the script.




<#     
    .NOTES 
    =========================================================================== 
    Created on:       4/02/2019 2:26 PM 
    Created by:       Vikas Sukhija 
    Organization:      
    Filename:         TeamsReport.ps1 
    =========================================================================== 
    .DESCRIPTION 
    This will report on AL teams across the tenant 
    Requires: Latest teams module and Exchaneg online Shell 
#>
 
############Script Parameters############## 
param ( 
  [string]$userId = $(throw "userid is required"),  
  [string]$password = $(throw "password is required"

#############Load Functions################# 
$error.clear() 
try { $null = Stop-Transcript } 
catch { $error.clear() } 
 
function Write-Log 

  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [array]$Name
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$Ext
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$folder
     
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create
     
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$Message
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$path
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')] 
    [ValidateSet('Information','Warning','Error')] 
    [string]$Severity = 'Information'
     
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG 
  ) 
  switch ($PsCmdlet.ParameterSetName) { 
    "Create" 
    { 
      $log = @() 
      $date1 = Get-Date -format d 
      $date1 = $date1.ToString().Replace("/""-"
      $time = Get-Date -format t 
     
      $time = $time.ToString().Replace(":""-"
      $time = $time.ToString().Replace(" """
     
      foreach ($n in $Name
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} 
      return $log 
    } 
    "Message" 
    { 
      $date = Get-Date 
      $concatmessage = "|$date" + "|   |" + $Message +"|  |" + "$Severity|" 
      switch($Severity){ 
        "Information"{Write-Host $concatmessage -ForegroundColor Green} 
        "Warning"{Write-Host $concatmessage -ForegroundColor Yellow} 
        "Error"{Write-Host $concatmessage -ForegroundColor Red} 
      } 
       
      Add-Content -Path $path -Value $concatmessage 
    } 
  } 

 
function LaunchEOL 

  param 
  ( 
    $cred 
  ) 
     
  $UserCredential = $cred 
     
  $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection 
     
  Import-PSSession $Session -Prefix "EOL" -AllowClobber 

Function RemoveEOL 

  $Session = Get-PSSession | where { $_.ComputerName -like "outlook.office365.com" } 
  Remove-PSSession $Session 

##########################Load variables & Logs#################### 
$log = Write-Log -Name "MSTeamOwnerReport" -folder logs -Ext log 
$output1 = Write-Log -Name "MSTeamOwner" -folder Report -Ext html 
 
$smtpserver = "SMTPserver" 
$from = "donotreply@labtest.com" 
$erroremail = "Reports@labtest.com" 
$collection =@() 
 
#####################Create folder and credential from arguments############### 
$logpath  = (Get-Location).path + "\logs"  
$testlogpath = Test-Path -Path $logpath 
if($testlogpath -eq $false
{New-Item -Path (Get-Location).path -Name Logs -Type directory} 
 
$reportpath = (Get-Location).path + "\Report" 
$testReportpath = Test-Path -Path $reportpath 
if($testReportpath -eq $false
{New-Item -Path (Get-Location).path -Name Report -Type directory} 
 
$pwd = $password | ConvertTo-SecureString -asPlainText -Force 
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId$pwd 
##########Start Script main############## 
 
Write-Log -Message "Script....Started" -path $log 
try 

  Connect-MicrosoftTeams -Credential $Credential 
  Write-Log -Message "Connected to teams Module" -path $log 

catch 

  $exception = $($_.Exception.Message) 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error Connecting MS Team Module MS Team Report" -Body $($_.Exception.Message) 
  Write-Log -Message "Exception occured connecting Teams module $exception" -path $log -Severity Error 
  Exit 

try 

  Write-Host "Connecting to EOL" -ForegroundColor Green 
  LaunchEOL -cred $Credential 
  Write-Log -Message "Connected to Exchange Online" -path $log 

catch 

  $exception = $($_.Exception.Message) 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error - EOL Connection MS Team Report" -Body $($_.Exception.Message) 
  Write-Log -Message "Exception occured connecting EOL Shell $exception" -path $log -Severity Error 
  Exit 

 
$collTeam = Get-Team | select DisplayName, GroupId, Description 
Write-Log -Message "feteched All Teams" -path $log 
Disconnect-MicrosoftTeams 
$collUnifiedGroup = get-EOLunifiedgroup -resultsize unlimited | select Name, AccessType, ExternalDirectoryObjectId, WhenCreated, ManagedByDetails, SharePointSiteUrl 
Write-Log -Message "feteched All Unified Groups" -path $log 
RemoveEOL 
Foreach($team in $collTeam

  $mcoll = "" | select Name, Description, GroupId, AccessType, WhenCreated, SharePointSiteUrl, ManagedByDetails 
  $teamdispname = $team.DisplayName 
  Write-Log -Message "Processing.............$teamdispname" -path $log 
  $mcoll.Name = $team.DisplayName 
  $mcoll.Description = $team.Description 
  $mcoll.GroupId = $team.groupId 
  foreach($ugroup in $collUnifiedGroup
  { 
    if($team.GroupId -eq $ugroup.ExternalDirectoryObjectId) 
    { 
      $mcoll.AccessType = $ugroup.AccessType 
      $mcoll.WhenCreated = $ugroup.WhenCreated 
      $mcoll.SharePointSiteUrl = $ugroup.SharePointSiteUrl 
      $mcoll.ManagedByDetails = $ugroup.ManagedByDetails 
    } 
  } 
   
  $collection +$mcoll 

 
############Format HTML########### 
$HTMLFormat = "" 
################################ 
$count = $collection.count 
$privateteams = $collection | where{$_.AccessType -eq "Private"
$publicteams = $collection | where{$_.AccessType -eq "Public"
$privateteamscount = $privateteams.count 
$publicteamscount = $publicteams.count 
 
Write-Log -Message "Converting to HTML" -path $log 
$collection | 
ConvertTo-Html -Head $HTMLFormat -Body "<H2><Font Size = 4,Color = DarkCyan>Microsoft Teams = $count, Private Teams = $privateteamscount, Public Teams = $publicteamscount  </Font></H2>" -AS Table | 
Set-Content $output1 
 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "MS Team Report" -Body "MS Team Report" -Attachments $output1 
Write-Log -Message "Report Sent to $erroremail" -path $log 
########################Recycle reports & logs############## 
$path1 = (Get-Location).path + "\report" 
$path2 = (Get-Location).path + "\Logs" 
$limit = (Get-Date).AddDays(-60) #for report recycling 
Get-ChildItem -Path $path1 | 
Where-Object -FilterScript {$_.CreationTime -lt $limit| 
Remove-Item -Recurse -Force 
 
Get-ChildItem -Path $path2 | 
Where-Object -FilterScript {$_.CreationTime -lt $limit| 
Remove-Item -Recurse -Force 
Write-Log -Message "Script....Finished" -path $log 
##############################################################################





Thanks for reading and downloading

Sukhija Vikas

http://SysCloudPro.com

12 comments:

  1. This script uses an unencrypted password. Why didn't you incorporate SecureString into your script?

    ReplyDelete
  2. Thanks for the feedback, we were running it manually when required(not often) & not as scheduled. I will update it to use encrypted password.
    Any ways I am converting it to secure string later in the script when incorporating the password in credentials..

    ReplyDelete
  3. The only problem is that once you ask for it the cat is out of the bag and if you hold it in a variable then its in memory for anyone to grab. I encrypt before I start and keep it on my computer to call into a script.

    ReplyDelete
  4. Good point, will update in new version..

    ReplyDelete
  5. Updated to accept secure string.

    ReplyDelete
  6. Hello i have received the following eror: Send-MailMessage : Service not available, closing transmission channel. The server response was: service not available (connection
    refused, too many connections)

    ReplyDelete
  7. |04/09/2019 17:57:39| |Converting to HTML| |Information|
    Send-MailMessage : Mailbox unavailable. The server response was: 5.5.0 Invalid EHLO/HELO domain.
    At TeamsReport.ps1:188 char:1
    + Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

    ReplyDelete
  8. Report is generated, you can check reports folder, issue is with your smtp server communication.

    ReplyDelete
  9. Where is that reports folder?

    ReplyDelete
  10. It would be inside the folder from where you have ran the script..

    ReplyDelete
  11. This report is great! It saved me a ton of time. Is it possible to output the report both in html and csv formats?
    Thanks!

    ReplyDelete
  12. Where you are seeing $collection just add another line
    $collection | export-csv "path to csv" and thats it.

    ReplyDelete