Skip to content

Instantly share code, notes, and snippets.

@jschlackman
Created November 29, 2022 15:49
Show Gist options
  • Select an option

  • Save jschlackman/8a82b1f1aa86000f10c65999cccfe097 to your computer and use it in GitHub Desktop.

Select an option

Save jschlackman/8a82b1f1aa86000f10c65999cccfe097 to your computer and use it in GitHub Desktop.
Searches for files that were created or modified more than a certain number of days ago and creates/emails an HTML report of any results.
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2022-11-29T12:00:00</Date>
<Author>[email protected]</Author>
<Description>Searches for files that were created or modified more than a certain number of days ago and creates/emails an HTML report of any results.</Description>
<URI>\Email Old File Details</URI>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2022-11-29T20:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>powershell</Command>
<Arguments>.\Email-OldFileDetails.ps1</Arguments>
<WorkingDirectory>C:\Scripts</WorkingDirectory>
</Exec>
</Actions>
</Task>
# Name: Email-OldFileDetails.ps1
# Author: James Schlackman
# Last Modified: November 29 2022
# Searches for files that were created or modified more than a certain number of days ago and creates/emails an HTML report of any results.
$SearchFilters = 'D:\*.pst'
$SearchAge = 365
$ReportTitle = 'PST files older than 1 Year'
$DiskReportLocation = 'T:\Logs\'
# Configure your mail relay and destination email address here
$MailRelay = 'smtp.contoso.com'
$FromAddress = 'Contoso File Server <[email protected]>'
$ToAddress = '[email protected]'
# Format file sizes with sensible units
Function Format-FileSize() {
Param ([int64]$size)
If ($size -gt 1TB) {[string]::Format("{0:0.00} TB", $size / 1TB)}
ElseIf ($size -gt 1GB) {[string]::Format("{0:0.00} GB", $size / 1GB)}
ElseIf ($size -gt 1MB) {[string]::Format("{0:0.0} MB", $size / 1MB)}
ElseIf ($size -gt 1KB) {[string]::Format("{0:0} KB", $size / 1KB)}
Else {[string]::Format("{0:0} B", $size)}
}
# Find matching files
$SearchResults = Get-ChildItem -Recurse -Path $SearchFilters | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-$SearchAge)) -or ($_.CreationTime -lt (Get-Date).AddDays(-$SearchAge))}
# If at least 1 result was found
If ($SearchResults) {
# Select useful properties and format for output
$SearchOutput = $SearchResults | Select @{Name='Path Name';Expression={$_.Fullname}},@{Name='Size';Expression={Format-FileSize $_.Length}},@{Name='Created';Expression={Get-Date -UFormat '%D' $_.CreationTime}},@{Name='Modified';Expression={Get-Date -UFormat '%D' $_.LastWriteTime}},@{Name='Accessed';Expression={Get-Date -UFormat '%D' $_.LastAccessTime}}
# Setup email styles and content
$ReportHead = "<style>body {font-family: Calibri,sans-serif; font-size: 11pt} h1 {font-family: Segoe UI Light,sans-serif} p.footer {margin-top: 3em; font-size: 9pt; font-style: italic; color: gray} table {background-color: #e6e6e6} td,th {background-color: white; padding: 3px} th {background-color: #f2f2f2}</style>"
$ReportBody = "<h1>Report: $ReportTitle</h1><p>The following files were either created or last modified more than $SearchAge days ago. They are probably due to be removed per data retention policy.</p><p><ul><li>Total files found: $($SearchResults.Count)</li><li>Total size: $(Format-FileSize ($SearchResults | Measure-Object -Property Length -Sum).Sum)</li></ul></p>"
$ReportFooter = "<p class=""footer"">This is a scripted message sent via the Task Scheduler on $env:COMPUTERNAME.</p>"
# Build email body text
$MailBody = $SearchOutput | ConvertTo-Html -Body $ReportBody -Title "Report: $ReportTitle" -PostContent $ReportFooter -Head $ReportHead | Out-String
# If a mail server is set, send the report in the body of an email message
If ($MailRelay) {
Send-MailMessage -SmtpServer $MailRelay -Subject "Report: $ReportTitle" -From $FromAddress -BodyAsHtml $MailBody -To $ToAddress
}
# If a location was specified to also store the report on disk, output it now
If ($DiskReportLocation) {
# Create the output location if it does not exist
If (!(Test-Path $DiskReportLocation)) {
New-Item -ItemType Directory $DiskReportLocation
}
$MailBody | Out-File -FilePath "$DiskReportLocation$((Get-Date).ToString("yyMMdd")) $ReportTitle.html"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment