Skip to content

Instantly share code, notes, and snippets.

@HurtzDonut
Last active April 27, 2018 14:33
Show Gist options
  • Save HurtzDonut/8ff0075c824991d2cdb255b097d37824 to your computer and use it in GitHub Desktop.
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.
<#
.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