IMG_7794

In the digital age, managing an email inbox can feel like a full-time job. Particularly in a business setting, where hundreds or even thousands of emails might flood in daily, keeping on top of your inbox can be a daunting task. Today, we’ll show you a PowerShell script designed to streamline your Microsoft Outlook inbox by identifying and deleting duplicate emails.

The Problem

Imagine you’re a system administrator or a developer in a large organization. You’ve set up notifications for system events or job statuses which are sent to your email. Sometimes, these notifications contain error messages with the word “Failed” in the subject. Over time, you might receive thousands of these notifications, many of which are identical. Sorting through these manually would be a tedious and time-consuming task.

The Solution

Enter PowerShell, a scripting language and shell framework used for task automation and configuration management. With PowerShell, we can create a script to automate the process of finding and deleting these duplicate emails.

The script works by leveraging the Outlook COM object to interact with the Outlook application. It then accesses the Inbox folder and creates a hashtable (a data structure used to store key-value pairs) to keep track of emails.

The script loops through each email in the Inbox. If the email’s subject contains the word “Failed”, it’s added to the hashtable. When adding emails to the hashtable, it uses the email’s subject as the key and the email itself as the value. This way, all emails with the same subject are grouped together.

The script then loops through the hashtable. If it finds any group of emails (i.e., emails with the same subject) that contains more than one email, it prompts the user for confirmation before deleting the duplicates. To ensure the most recent email is kept, it sorts the emails by their ReceivedTime property in descending order and then moves all but the most recent email to a “Backup” folder.

Time Savings

This script can save hours each day, especially for those who receive thousands of duplicate emails. Instead of manually going through each email, the script does all the work for you. All you need to do is confirm whether you want to delete the duplicates. Moreover, it keeps your inbox organized, making it easier to focus on new and important emails.

Use Cases

While the script is designed to handle a specific scenario (deleting duplicate emails with “Failed” in the subject), it can easily be modified for other use cases. For example, you could adjust the script to find and delete any duplicate emails, regardless of their subject. You could also modify the script to move emails to different folders based on their subjects, senders, or other properties.

How does the script work?

  1. Launch Outlook Instance: The script begins by creating a new instance of the Outlook application. This instance is stored in a variable for further use.
  2. Access Inbox: Next, it gets a Namespace object representing the Messaging Application Programming Interface (MAPI), which is used for managing and manipulating email data. It then accesses the default Inbox folder.
  3. Check for Backup Folder: The script checks if a folder named “Backup” exists in the Inbox. If it doesn’t, the script creates this folder. This folder is used to store the duplicate emails that will be moved from the Inbox.
  4. Create Hashtable: The script creates a hashtable to store emails. The key of each entry in the hashtable is the subject of an email, and the value is an array of emails that have this subject.
  5. Process Emails: The script loops through each email in the Inbox. If the subject of an email contains the word “Failed”, the email is added to the hashtable.
  6. Delete Duplicates: The script then loops through the hashtable. If it finds any group of emails (i.e., emails with the same subject) that contains more than one email, it prompts the user for confirmation before deleting the duplicates. To ensure the most recent email is kept, it sorts the emails by their ReceivedTime property in descending order and then moves all but the most recent email to the “Backup” folder.
  7. Release Resources: At the end of the script, it releases the COM object and forces garbage collection, which is a good practice when working with COM objects in PowerShell to free up system resources.

The Script

# Script parameter: $autoConfirm
param (
    [bool]$autoConfirm = $true
)

# Create an instance of Outlook
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")

# Access the Inbox
$inbox = $namespace.GetDefaultFolder(6)

# Check if a Backup folder exists, if not, create it
$backupFolder = $inbox.Folders | Where-Object { $_.Name -eq "Backup" }
if ($null -eq $backupFolder) {
    $backupFolder = $inbox.Folders.Add("Backup")
}

# Create a hashtable to store emails
$emailTable = @{}

# Loop through each email in the Inbox
foreach ($email in $inbox.Items) {
    if ($email.Subject -like "*Failed*") {
        # Add the email to the hashtable
        if ($emailTable.ContainsKey($email.Subject)) {
            $emailTable[$email.Subject] += ,$email
        } else {
            $emailTable[$email.Subject] = @($email)
        }
    }
}

# Counter to keep track of current progress
$counter = 0

# Loop through the hashtable and prompt to delete duplicates
foreach ($entry in $emailTable.GetEnumerator()) {
    # Calculate the progress
    $progress = (++$counter / $emailTable.Count) * 100
    Write-Progress -Activity "Processing emails" -Status "$counter of $($emailTable.Count)" -PercentComplete $progress
    
    if ($entry.Value.Count -gt 1) {
        if ($autoConfirm) {
            $confirmation = "y"
        } else {
            $confirmation = Read-Host "Duplicate emails found with subject: $($entry.Key). Do you want to delete the duplicates? (y/n)"
        }
        
        if ($confirmation -eq 'y') {
            # Sort the emails by ReceivedTime, in descending order
            $sortedEmails = $entry.Value | Sort-Object ReceivedTime -Descending
            
            # Skip the first email (index 0, the most recent), move the rest to backup folder
            for ($i = 1; $i -lt $sortedEmails.Count; $i++) {
                Write-Host "Moving duplicate email with subject '$($sortedEmails[$i].Subject)' to Backup folder."
                $null = $sortedEmails[$i].Move($backupFolder)
            }
        }
    }
}

# Release the COM object
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($outlook) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Found priceless insights in this blog? Support the author’s creativity – buy them a coffee!

Leave a Reply

Your email address will not be published. Required fields are marked *