From c2cc18746c39a6a018bc95e4f022545e1a9b26af Mon Sep 17 00:00:00 2001 From: Tony Redmond <45732130+12Knocksinna@users.noreply.github.com> Date: Mon, 17 Dec 2018 20:27:15 +0000 Subject: [PATCH 1/2] Add files via upload Fixed bug! --- SPOSitesRetention.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPOSitesRetention.ps1 b/SPOSitesRetention.ps1 index c72a07f..47f30d6 100644 --- a/SPOSitesRetention.ps1 +++ b/SPOSitesRetention.ps1 @@ -13,7 +13,7 @@ ForEach ($P in $Policies) { # Check whether a rule is for advanced settings - either a KQL query or sensitive data types If (-not [string]::IsNullOrWhiteSpace($Rule.ContentMatchQuery) -and -not [string]::IsNullOrWhiteSpace($Rule.ContentMatchQuery)) { $Settings = "Advanced/KQL" } - Elseif (-not [string]::IsNullOrWhiteSpace($Rule.ContentContainsSensitiveInformation) -and -not [string]::IsNullOrWhiteSpace($Rule.ContentContainsSensitiveInformation)) { + Elseif (-not [string]::IsNullOrWhiteSpace($Rule.ContentContainsSensitiveInformation) -and -not [string]::IsNullOrEmpty($Rule.ContentContainsSensitiveInformation)) { $Settings = "Advanced/Sensitive Data" } # Handle retention policy that simply retains and doesn't do anything else If ($Rule.RetentionDuration -eq $Null -and $Rule.ApplyComplianceTag -ne $Null) { From e168ebf905e88144deda26e355b0e2c6467e0b52 Mon Sep 17 00:00:00 2001 From: Tony Redmond <45732130+12Knocksinna@users.noreply.github.com> Date: Mon, 17 Dec 2018 20:34:48 +0000 Subject: [PATCH 2/2] Add files via upload V3.0 of the file published through the TechNet Gallery --- TeamsGroupsActivityReport.ps1 | 213 ++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 TeamsGroupsActivityReport.ps1 diff --git a/TeamsGroupsActivityReport.ps1 b/TeamsGroupsActivityReport.ps1 new file mode 100644 index 0000000..ca05f73 --- /dev/null +++ b/TeamsGroupsActivityReport.ps1 @@ -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=" + + +
+

Office 365 Groups and Teams Activity Report

+

Generated: " + $date + "

" + +# 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 = "

Report created for: " + $OrgName + " +

+

Number of groups scanned: " + $Groups.Count + "

" + + "

Number of potentially obsolete groups (based on document library activity): " + $ObsoleteSPOGroups + "

" + + "

Number of potentially obsolete groups (based on conversation activity): " + $ObsoleteEmailGroups + "

"+ + "

Number of Teams-enabled groups : " + $TeamsList.Count + "

" + + "

Percentage of Teams-enabled groups: " + ($PercentTeams).tostring("P") + "" +$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 +