Last active
April 27, 2018 14:33
-
-
Save HurtzDonut/8ff0075c824991d2cdb255b097d37824 to your computer and use it in GitHub Desktop.
Searches for and removes Lotus Notes documents older than a specified date or larger than a specified size.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Searches for and removes Notes documents older than a specified date or larger than a specified size. | |
.DESCRIPTION | |
Connects to Users Notes Database through COM to search for and delete files older than a specified date, or files larger than a specified size. | |
.PARAMETER FolderName | |
Specifies which folder(s) to look through. | |
.PARAMETER Days | |
Defines the maximum age for documents. Any documents older than this date will be removed. Must be >= 1. | |
.PARAMETER LotusServer | |
Specifies the server where the mail file lives. | |
.PARAMETER LNMailFile | |
Defines the name for the Lotus Notes mail file. Calculated from AD with 1st initial and last name. | |
If the calculated value is causing issues, your mail file can be explicitly set with the following syntax: | |
"mail/mailfile.nsf". | |
This can be found in Notes [ Alt+Enter > Change 'Document' to 'Database' > Filename: ] | |
.PARAMETER Log | |
Specifies the location of the log file. | |
.PARAMETER SizeLimit | |
The size limit, in MB, for a single document. Default is 10. Must be >= 1. | |
.EXAMPLE | |
Remove-NotesDocuments -FolderName '($Sent)' | |
Serarches through ($Sent) for docs older than 30 days. | |
.EXAMPLE | |
Remove-NotesDocuments -FolderNames '($Inbox)','($Drafts)' -SizeLimit 20 | |
Searches through ($Inbox) & ($Drafts) for docs older than 30 days, and larger than 20MB | |
.EXAMPLE | |
Remove-NotesDocuments -FN '($Inbox)' -Age 14 -Size 5 | |
# Searches through ($Inbox) for docs older than 14 days, and larger than 5MB | |
.EXAMPLE | |
Remove-NotesDocuments | |
Searches through ($All) for docs older than 30 Days. | |
.EXAMPLE | |
Remove-NotesDocuments -FN '($Inbox)' -D 14 -SN 'NotesSrv.domain.local' -MF 'mail/user1.nsf' -LF 'C:\Temp\LotusLog.txt' -SL 15 | |
Searches through '($Inbox)' in 'User1's mail file on 'NotesSrv.domain.local' for documents older than '14' days or larger than '15'MB. | |
Logs to 'C:\Temp\LotusLog.txt' | |
.LINK | |
http://invisibleroads.com/tutorials/notes-mail-read-win32com.html | |
.LINK | |
http://www-12.lotus.com/ldd/doc/domino_notes/6.5.1/help65_designer.nsf/f4b82fbb75e942a6852566ac0037f284/e94eb03c53a1d96485256e00004a447b?OpenDocument | |
.NOTES | |
AUTHOR: /u/_Cabbage_Corp_ | |
CREATED: 2017/11/08 | |
LAST MODIFIED: 2018/04/27 | |
The majority of the script was modifed from code found in the links. | |
Link(InvisibleRoads): Code written in Python, but very handy for syntax of LN objects. | |
Link(Lotus): LotusScript Classes Coding Guidelines. Detailed info for LN COM objects. | |
###################~~!!Non-Elevated 32-bit PowerShell Required!!~~######################## | |
# A list of all Views(Folders) can be retreived by running the following: # | |
# # | |
# # | |
# $User = Get-ADUser -Filter "SAMAccountName -eq '$env:USERNAME'" # | |
# $LNMailFile = "mail/" + $User.GivenName.ToLower()[0] + $User.Surname.ToLower() +".nsf" # | |
# $LotusServer = "IUBMAIL01" # | |
# $DominoSession = New-Object -ComObject Lotus.NotesSession # | |
# $DominoSession.Initialize # | |
# $NotesDB = $DominoSession.GetDatabase($LotusServer,$LNMailFile) # | |
# $NotesDB.Views | Select -ExpandProperty Name | Sort # | |
# _________________________________________ # | |
# | Some Common folders [Same for everyone] | # | |
# | ($All) ($Calendar) | # | |
# | ($Inbox) ($Drafts) | # | |
# | ($Trash) ($Contacts) | # | |
# | -To Be Deleted ($Sent) | # | |
# |_________________________________________| # | |
########################################################################################## | |
#> | |
#Requires -Modules ActiveDirectory | |
[CmdletBinding(DefaultParameterSetName = 'Age')] | |
param( | |
[Parameter(ParameterSetName = 'Age', Mandatory)] | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('Folders', 'FolderNames', 'FN')] | |
[string[]]$FolderName = '($All)', | |
[Parameter(ParameterSetName = 'Age')] | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('DocumentAge', 'Age', 'D')] | |
[ValidateScript( {$_ -ge 1})] | |
[int]$Days = 30, | |
[Parameter(ParameterSetName = 'Age')] | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('Server', 'Domino', 'Srv', 'SN')] | |
[string]$LotusServer = 'IUBMAIL01.msfg.wan', | |
[Parameter(ParameterSetName = 'Age')] | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('Mailbox', 'MF')] | |
[string]$LNMailFile = $( | |
$User = Get-ADUser -Filter "SAMAccountName -eq '$env:USERNAME'" | |
-join ("mail/", $User.GivenName.ToLower()[0], $User.Surname.ToLower(), ".nsf") | |
), | |
[Parameter(ParameterSetName = 'Age')] | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('LF')] | |
[string]$Log = "$([environment]::GetFolderPath('Desktop'))\$(Get-Date -f yyMMdd)_Cleanup.log", | |
[Parameter(ParameterSetName = 'Size')] | |
[Alias('Limit', 'Size', 'SL')] | |
[ValidateScript( {$_ -ge 1})] | |
[int]$SizeLimit = 10) | |
Begin { | |
# Script requires 32-bit | |
Write-Verbose 'Verifying powershell is running in x86 mode.' | |
If ([Environment]::Is64BitProcess) { | |
$Title = "64-bit PowerShell Detected!" | |
$message = "Powershell is running in 64-bit mode.`nThis script requires PowerShell be in 32-bit mode.`nWould you like to launch PowerShell in 32-bit mode?" | |
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Launches 32-bit PowerShell process" | |
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Exits Script." | |
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) | |
$result = $host.ui.PromptForChoice($title, $message, $options, 0) | |
Switch ($result) { | |
0 { | |
# Get the passed parameters from the command | |
[String]$ParameterList = $MyInvocation.BoundParameters.Keys | ForEach {$Key = $_; (Get-Variable $Key -ErrorAction SilentlyContinue).Value } | ForEach { -join ("-$Key $_", '')} | |
$arguments = -join ("-ExecutionPolicy Bypass -File ", $myinvocation.mycommand.definition, ' ', $ParameterList) | |
# Start powershell.exe (x86) with the passed parameters | |
Start-Process $env:SystemRoot\syswow64\WindowsPowerShell\v1.0\powershell.exe -ArgumentList $arguments | |
Exit | |
} | |
1 { | |
Exit | |
} | |
} | |
} else { | |
Write-Verbose "Architecture Check Passed!`nScript will now proceed." | |
} # End 32/64 Check | |
# Variables | |
$DocCount = 0 | |
$SizeLimit = $SizeLimit * 1MB | |
$AgeLimit = (Get-Date).AddDays(-$Days) | |
$DocsToDelete = New-Object System.Collections.ArrayList | |
Write-Verbose 'Checking for log file...' | |
If (-not (Test-Path $Log)) { | |
Write-Verbose 'Log file not found. Creating new.' | |
New-Item $Log -ItemType File | Out-Null | |
} | |
# Create and Intialize COM Object | |
Try { | |
Write-Verbose 'Attempting to initialize Lotus Notes COM Session.' | |
$DominoSession = New-Object -ComObject Lotus.NotesSession | |
$DominoSession.Initialize() | |
} Catch { | |
Write-Warning $_.Exception.Message | |
Write-Warning "Failed to Intialize Lotus.NotesSession.`n`t Script Cannot Continue.`n`t Exiting..." | |
Exit | |
} | |
# Open mail file | |
Try { | |
Write-Verbose 'Attempting to open mail file.' | |
$NotesDB = $DominoSession.GetDatabase($LotusServer, $LNMailFile) | |
} Catch { | |
Write-Warning $_.Exception.Message | |
Write-Warning "Failed to open mail file.`n`t Script Cannot Continue.`n`t Exiting..." | |
Exit | |
} | |
} # Begin | |
Process { | |
Write-Verbose 'Getting first document' | |
ForEach ($Folder in $FolderName) { | |
$OpenView = $NotesDB.GetView("$Folder") | |
$Document = $OpenView.GetFirstDocument() | |
Write-Verbose 'Checking ParameterSetName' | |
While ($Document) { | |
Switch ($PSCmdlet.ParameterSetName) { | |
'Size' { | |
$Bool = ($Document.Created -lt $AgeLimit) -or ($Document.Size -ge $SizeLimit) | |
} # Age & Size | |
Default { | |
$Bool = $Document.Created -lt $AgeLimit | |
} # Age Only | |
} # End ParameterSetName check | |
Write-Progress -Activity ('Processing {0} documents' -F ($OpenView.EntryCount)) ` | |
-Status ('{0} matching docs found' -F $DocCount) ` | |
-CurrentOperation "$($Document.Created) | $($Document.GetItemValue('From')) | $($Document.GetItemValue('Subject'))" | |
If ($Bool) { | |
$objDoc = [PSCustomObject]@{ | |
From = $Document.GetItemValue('From') | |
Subject = $Document.GetItemValue('Subject') | |
Created = $Document.Created | |
'Size_(B)' = $Document.Size | |
} | |
$DocCount++ | |
Write-Verbose 'Logging Document info for later.' | |
$DocsToDelete.Add($objDoc) | Out-Null | |
Write-Verbose 'Holding document in [-To Be Deleted]' | |
$Document.PutInFolder('-To Be Deleted') | |
} # End DocMove | |
Write-Verbose ('Getting next document in {0}' -f $Folder) | |
$Document = $OpenView.GetNextDocument($Document) | |
} # End Document Processing | |
} # End Loop through $FolderName array | |
Write-Progress -Activity 'Finished Processing.' -Status (' # of matching documents: {0}' -F $DocCount) -Completed | |
} # Process | |
End { | |
# Load All Docs in the '-To Be Deleted' folder (Since we determined these are over the age limit) | |
Write-Verbose 'Getting all documents in [-To Be Deleted].' | |
$tbdFolder = ($NotesDB.GetView('-To Be Deleted')).AllEntries | |
# Load First Doc in Folder | |
$tbdEntry = $tbdFolder.GetFirstEntry() | |
Write-Verbose 'Moving documents to ($Trash).' | |
$i = 0 | |
While ($tbdEntry) { | |
Write-Progress -Activity "Soft Deleting documents" -Status "Processing..." -CurrentOperation "Deleted $i of $($tbdFolder.count)" | |
# '.Remove' is a "Soft Delete" aka. the $Doc moves to Trash folder | |
# It is possible to do a hard delete using '.RemovePermanently($True)', however, | |
# this causes navigation to the next document to fail. | |
# As such, I elected to only delete 1 document at time. | |
# I recommend leaving the Soft Delete in Place. | |
# If you wish to remove docs permanently, empty the Trash folder when this script is done. | |
Try { | |
$tbdEntry.Document.Remove($True) | Out-Null | |
} Catch { | |
Add-Content -Path $Log -Value "Failed to remove document: $($tbdEntry.Document)" | |
} | |
# Move to Next Doc | |
$tbdEntry = $tbdFolder.GetNextEntry($tbdEntry) | |
$i++ | |
} # End RemDoc process | |
Write-Progress -Activity "Document deletion completed" -Status "Completed" -Completed | |
# Add List of Removed Docs to $OutFile wich is recorded in $Log | |
Write-Verbose ('Adding all logged document info to {0}' -F $Log) | |
$OutFile = $DocsToDelete | FT -AutoSize | Out-String -Width 4000 | |
Add-Content -Path $Log -Value "Total Document Count: $DocCount" | |
Add-Content -Path $Log -Value $OutFile | |
# Release COM Object | |
Write-Verbose 'Ending Lotus Notes COM Session' | |
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($DominoSession) | Out-Null | |
} # End |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment