Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
V3.0 of the file published through the TechNet Gallery
  • Loading branch information
12Knocksinna authored Dec 17, 2018
1 parent c2cc187 commit e168ebf
Showing 1 changed file with 213 additions and 0 deletions.
213 changes: 213 additions & 0 deletions TeamsGroupsActivityReport.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# A script to check the activity of Office 365 Groups and Teams and report the groups and teams that might be deleted because they're not used.
# We check the group mailbox to see what the last time a conversation item was added to the Inbox folder.
# Another check sees whether a low number of items exist in the mailbox, which would show that it's not being used.
# We also check the group document library in SharePoint Online to see whether it exists or has been used in the last 90 days.
# And we check Teams compliance items to figure out if any chatting is happening.

# Created 29-July-2016 Tony Redmond
# V2.0 5-Jan-2018
# V3.0 17-Dec-2018

# Check that we are connected to Exchange Online
Write-Host "Checking that prerequisite PowerShell modules are loaded..."
Try { $OrgName = (Get-OrganizationConfig).Name }
Catch {
Write-Host "Your PowerShell session is not connected to Exchange Online."
Write-Host "Please connect to Exchange Online using an administrative account and retry."
Break }

# And check that we're connected to SharePoint Online as well
Try { $SPOCheck = (Get-SPOTenant -ErrorAction SilentlyContinue ) }
Catch {
Write-Host "Your PowerShell session is not connected to SharePoint Online."
Write-Host "Please connect to SharePoint Online using an administrative account and retry."
Break }

# And finally the Teams module
Try { $TeamsCheck = (Get-Team) }
Catch {
Write-Host "Please connect to the Teams PowerShell module before proceeeding."
Break }

# OK, we seem to be fully connected to both Exchange Online and SharePoint Online...
Write-Host "Checking for Obsolete Office 365 Groups in the tenant:" $OrgName

# Setup some stuff we use
$WarningDate = (Get-Date).AddDays(-90)
$WarningEmailDate = (Get-Date).AddDays(-365)
$Today = (Get-Date)
$Date = $Today.ToShortDateString()
$TeamsGroups = 0
$TeamsEnabled = $False
$ObsoleteSPOGroups = 0
$ObsoleteEmailGroups = 0
$Report = @()
$ReportFile = "c:\temp\GroupsActivityReport.html"
$CSVFile = "c:\temp\GroupsActivityReport.csv"
$htmlhead="<html>
<style>
BODY{font-family: Arial; font-size: 8pt;}
H1{font-size: 22px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
H2{font-size: 18px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
H3{font-size: 16px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
TABLE{border: 1px solid black; border-collapse: collapse; font-size: 8pt;}
TH{border: 1px solid #969595; background: #dddddd; padding: 5px; color: #000000;}
TD{border: 1px solid #969595; padding: 5px; }
td.pass{background: #B7EB83;}
td.warn{background: #FFF275;}
td.fail{background: #FF2626; color: #ffffff;}
td.info{background: #85D4FF;}
</style>
<body>
<div align=center>
<p><h1>Office 365 Groups and Teams Activity Report</h1></p>
<p><h3>Generated: " + $date + "</h3></p></div>"

# Get a list of all Office 365 Groups in the tenant
Write-Host "Extracting list of Office 365 Groups for checking..."
$Groups = Get-UnifiedGroup -ResultSize Unlimited | Sort-Object DisplayName
# And create a hash table of Teams
$TeamsList = @{}
Get-Team | ForEach { $TeamsList.Add($_.GroupId, $_.DisplayName) }

Write-Host "Processing" $Groups.Count "groups"
# Progress bar
$ProgDelta = 100/($Groups.count)
$CheckCount = 0
$GroupNumber = 0

# Main loop
ForEach ($G in $Groups) {
$GroupNumber++
$GroupStatus = $G.DisplayName + " ["+ $GroupNumber +"/" + $Groups.Count + "]"
Write-Progress -Activity "Checking group" -Status $GroupStatus -PercentComplete $CheckCount
$CheckCount += $ProgDelta
$ObsoleteReportLine = $G.DisplayName
$SPOStatus = "Normal"
$SPOActivity = "Document library in use"
$NumberWarnings = 0
$NumberofChats = 0
$TeamChatData = $Null
$TeamsEnabled = $False
$LastItemAddedtoTeams = "No chats"
$MailboxStatus = $Null
# Check who manages the group
$ManagedBy = $G.ManagedBy
If ([string]::IsNullOrWhiteSpace($ManagedBy) -and [string]::IsNullOrEmpty($ManagedBy)) {
$ManagedBy = "No owners"
Write-Host $G.DisplayName "has no group owners!" -ForegroundColor Red}
Else {
$ManagedBy = (Get-Mailbox -Identity $G.ManagedBy[0]).DisplayName}

# Fetch information about activity in the Inbox folder of the group mailbox
$Data = (Get-MailboxFolderStatistics -Identity $G.Alias -IncludeOldestAndNewestITems -FolderScope Inbox)
$LastConversation = $Data.NewestItemReceivedDate
$NumberConversations = $Data.ItemsInFolder
$MailboxStatus = "Normal"

If ($Data.NewestItemReceivedDate -le $WarningEmailDate) {
Write-Host "Last conversation item created in" $G.DisplayName "was" $Data.NewestItemReceivedDate "-> Obsolete?"
$ObsoleteReportLine = $ObsoleteReportLine + " Last conversation dated: " + $Data.NewestItemReceivedDate + "."
$MailboxStatus = "Group Inbox Not Recently Used"
$ObsoleteEmailGroups++
$NumberWarnings++ }
Else
{# Some conversations exist - but if there are fewer than 20, we should flag this...
If ($Data.ItemsInFolder -lt 20) {
$ObsoleteReportLine = $ObsoleteReportLine + " Only " + $Data.ItemsInFolder + " conversation item(s) found."
$MailboxStatus = "Low number of conversations"
$NumberWarnings++}
}

# Loop to check SharePoint document library
If ($G.SharePointDocumentsUrl -ne $Null) {
$SPOSite = (Get-SPOSite -Identity $G.SharePointDocumentsUrl.replace("/Shared Documents", ""))
$AuditCheck = $G.SharePointDocumentsUrl + "/*"
$AuditRecs = 0
$AuditRecs = (Search-UnifiedAuditLog -RecordType SharePointFileOperation -StartDate $WarningDate -EndDate $Today -ObjectId $AuditCheck -SessionCommand ReturnNextPreviewPage)
If ($AuditRecs -eq $null) {
#Write-Host "No audit records found for" $SPOSite.Title "-> Potentially obsolete!"
$ObsoleteSPOGroups++
$ObsoleteReportLine = $ObsoleteReportLine + " No SPO activity detected in the last 90 days." }
}
Else
{
# The SharePoint document library URL is blank, so the document library was never created for this group
#Write-Host "SharePoint has never been used for the group" $G.DisplayName
$ObsoleteSPOGroups++
$ObsoleteReportLine = $ObsoleteReportLine + " SPO document library never created."
}
# Report to the screen what we found - but only if something was found...
If ($ObsoleteReportLine -ne $G.DisplayName)
{
Write-Host $ObsoleteReportLine
}
# Generate the number of warnings to decide how obsolete the group might be...
If ($AuditRecs -eq $Null) {
$SPOActivity = "No SPO activity detected in the last 90 days"
$NumberWarnings++ }
If ($G.SharePointDocumentsUrl -eq $Null) {
$SPOStatus = "Document library never created"
$NumberWarnings++ }

$Status = "Pass"
If ($NumberWarnings -eq 1)
{
$Status = "Warning"
}
If ($NumberWarnings -gt 1)
{
$Status = "Fail"
}

# If Team-Enabled, we can find the date of the last chat compliance record
If ($TeamsList.ContainsKey($G.ExternalDirectoryObjectId) -eq $True) {
$TeamsEnabled = $True
$TeamChatData = (Get-MailboxFolderStatistics -Identity $G.Alias -IncludeOldestAndNewestItems -FolderScope ConversationHistory)
If ($TeamChatData.ItemsInFolder[1] -ne 0) {
$LastItemAddedtoTeams = $TeamChatData.NewestItemReceivedDate[1]
$NumberofChats = $TeamChatData.ItemsInFolder[1]
If ($TeamChatData.NewestItemReceivedDate -le $WarningEmailDate) {
Write-Host "Team-enabled group" $G.DisplayName "has only" $TeamChatData.ItemsInFolder[1] "compliance record(s)" }
}
}

# Generate a line for this group for our report
$ReportLine = [PSCustomObject][Ordered]@{
GroupName = $G.DisplayName
ManagedBy = $ManagedBy
Members = $G.GroupMemberCount
ExternalGuests = $G.GroupExternalMemberCount
Description = $G.Notes
MailboxStatus = $MailboxStatus
TeamEnabled = $TeamsEnabled
LastChat = $LastItemAddedtoTeams
NumberChats = $NumberofChats
LastConversation = $LastConversation
NumberConversations = $NumberConversations
SPOActivity = $SPOActivity
SPOStatus = $SPOStatus
NumberWarnings = $NumberWarnings
Status = $Status}
# And store the line in the report object
$Report += $ReportLine
#End of main loop
}
# Create the HTML report
$PercentTeams = ($TeamsList.Count/$Groups.Count)
$htmlbody = $Report | ConvertTo-Html -Fragment
$htmltail = "<p>Report created for: " + $OrgName + "
</p>
<p>Number of groups scanned: " + $Groups.Count + "</p>" +
"<p>Number of potentially obsolete groups (based on document library activity): " + $ObsoleteSPOGroups + "</p>" +
"<p>Number of potentially obsolete groups (based on conversation activity): " + $ObsoleteEmailGroups + "<p>"+
"<p>Number of Teams-enabled groups : " + $TeamsList.Count + "</p>" +
"<p>Percentage of Teams-enabled groups: " + ($PercentTeams).tostring("P") + "</body></html>"
$htmlreport = $htmlhead + $htmlbody + $htmltail
$htmlreport | Out-File $ReportFile -Encoding UTF8

# Summary note
Write-Host $ObsoleteSPOGroups "obsolete group document libraries and" $ObsoleteEmailGroups "obsolete email groups found out of" $Groups.Count "checked"
Write-Host "Summary report available in" $ReportFile "and CSV file saved in" $CSVFile
$Report | Export-CSV -NoTypeInformation $CSVFile

0 comments on commit e168ebf

Please sign in to comment.