-
-
Save dwightmulcahy/646519777b1283dfeb0cc1f0a6b148c6 to your computer and use it in GitHub Desktop.
| // ---------------------------- | |
| // --- GLOBAL CONFIGURATION --- | |
| // ---------------------------- | |
| // Define the list of Gmail folders (labels) to be cleaned. | |
| // To specify a custom label that is nested under another, use a forward slash '/'. | |
| const FOLDERS_TO_CLEAN = ["Trash", "Spam", "My Custom Label"]; // <--- CONFIGURE YOUR FOLDERS HERE | |
| // Define a list of email addresses from which to delete messages. | |
| // If this list is empty, the script will delete messages from ALL senders | |
| // found within the FOLDERS_TO_CLEAN. | |
| const SENDERS_TO_DELETE = ["unwanted.sender@example.com", "another.spam@domain.net"]; // <--- CONFIGURE SENDERS TO DELETE HERE | |
| // Define a list of email addresses to explicitly exclude from deletion. | |
| // Messages from these senders will NOT be deleted, even if they are in the | |
| // FOLDERS_TO_CLEAN or from a sender on the SENDERS_TO_DELETE list. | |
| const SENDERS_TO_EXCLUDE = ["important.person@work.com", "do-not-touch@family.net"]; // <--- CONFIGURE SENDERS TO EXCLUDE HERE | |
| // Define the maximum duration (in minutes) for the script to run. | |
| const MAX_CLEANUP_DURATION_MINUTES = 5; // <--- CONFIGURE MAX DURATION IN MINUTES HERE | |
| // ---------------------------- | |
| /** | |
| * Permanently deletes messages from specified Gmail folders (labels). | |
| * The script can be configured to delete from specific senders, all senders, | |
| * and to exclude certain senders from the deletion process. | |
| */ | |
| function emptyGmailTrash() { | |
| const MAX_DURATION_MS = MAX_CLEANUP_DURATION_MINUTES * 60 * 1000; | |
| const startTime = Date.now(); | |
| var folderThreadCounts = {}; | |
| var totalThreadsProcessed = 0; | |
| var messagesCollectedCount = 0; | |
| var messagesSuccessfullyDeletedCount = 0; | |
| var timeLimitHit = false; | |
| var deletionAttempted = false; | |
| var deletionSuccessful = false; | |
| var deletionErrorMessage = "No error."; | |
| // --- Step 1: Construct the Search Query --- | |
| Logger.log("Constructing the search query..."); | |
| let searchQuery = ""; | |
| // Combine folders into an 'in:' or 'label:' operator string | |
| if (FOLDERS_TO_CLEAN && FOLDERS_TO_CLEAN.length > 0) { | |
| let folderQueries = FOLDERS_TO_CLEAN.map(folder => `in:${folder.toLowerCase()}`).join(" OR "); | |
| searchQuery += `(${folderQueries})`; | |
| } else { | |
| // If no folders are specified, we can't perform the action. | |
| Logger.log("Error: No folders specified in FOLDERS_TO_CLEAN. Exiting."); | |
| logSummary(); | |
| return; | |
| } | |
| // Add senders to include, if any | |
| if (SENDERS_TO_DELETE && SENDERS_TO_DELETE.length > 0) { | |
| let senderQueries = SENDERS_TO_DELETE.map(sender => `from:"${sender}"`).join(" OR "); | |
| searchQuery += ` AND (${senderQueries})`; | |
| Logger.log("Action: Deleting messages from specific senders."); | |
| } else { | |
| Logger.log("Action: Deleting all messages within specified folders."); | |
| } | |
| // Add senders to exclude, if any | |
| if (SENDERS_TO_EXCLUDE && SENDERS_TO_EXCLUDE.length > 0) { | |
| let excludeQueries = SENDERS_TO_EXCLUDE.map(sender => `-from:"${sender}"`).join(" "); | |
| searchQuery += ` ${excludeQueries}`; | |
| Logger.log("Excluding messages from specific senders."); | |
| } | |
| Logger.log(`Final Search Query: ${searchQuery}`); | |
| // --- Step 2: Retrieve Threads using the Constructed Query --- | |
| var threadsToProcess = []; | |
| try { | |
| const threads = GmailApp.search(searchQuery); | |
| totalThreadsProcessed = threads.length; | |
| if (totalThreadsProcessed > 0) { | |
| Logger.log(`Found ${totalThreadsProcessed} threads matching the query.`); | |
| threadsToProcess = threads; | |
| } else { | |
| Logger.log("No threads found matching the search criteria. Exiting."); | |
| logSummary(); | |
| return; | |
| } | |
| } catch (e) { | |
| Logger.log(`Error searching for threads: ${e.toString()}`); | |
| deletionErrorMessage = `Error searching for threads: ${e.toString()}`; | |
| logSummary(); | |
| return; | |
| } | |
| // --- Step 3: Collect Message IDs from All Identified Threads --- | |
| var messageIdsToDelete = []; | |
| Logger.log("Collecting message IDs from identified threads..."); | |
| for (var i = 0; i < threadsToProcess.length; i++) { | |
| if ((Date.now() - startTime) > MAX_DURATION_MS) { | |
| Logger.log("Time limit reached during thread iteration. Processing collected IDs so far."); | |
| timeLimitHit = true; | |
| break; | |
| } | |
| var messages = threadsToProcess[i].getMessages(); | |
| for (var j = 0; j < messages.length; j++) { | |
| if ((Date.now() - startTime) > MAX_DURATION_MS) { | |
| Logger.log("Time limit reached during message ID collection. Collected " + messageIdsToDelete.length + " message IDs so far."); | |
| timeLimitHit = true; | |
| break; | |
| } | |
| messageIdsToDelete.push(messages[j].getId()); | |
| } | |
| if (timeLimitHit) { | |
| break; | |
| } | |
| } | |
| messagesCollectedCount = messageIdsToDelete.length; | |
| // --- Step 4: Perform Batch Deletion --- | |
| if (messagesCollectedCount > 0) { | |
| Logger.log("Attempting to permanently delete " + messagesCollectedCount + " messages using batch delete..."); | |
| deletionAttempted = true; | |
| try { | |
| Gmail.Users.Messages.batchDelete({ | |
| ids: messageIdsToDelete | |
| }, 'me'); | |
| messagesSuccessfullyDeletedCount = messagesCollectedCount; | |
| deletionSuccessful = true; | |
| Logger.log("Successfully deleted " + messagesSuccessfullyDeletedCount + " messages."); | |
| } catch (e) { | |
| Logger.log("FAILED to delete messages. Error: " + e.toString()); | |
| deletionErrorMessage = "Deletion failed: " + e.toString(); | |
| } | |
| } else { | |
| Logger.log("No message IDs found to delete after collection process."); | |
| } | |
| // --- Final Summary Log --- | |
| function logSummary() { | |
| Logger.log("\n--- Gmail Cleanup Summary ---"); | |
| Logger.log(`Script Start Time: ${new Date(startTime).toLocaleString()}`); | |
| Logger.log(`Configured Max Duration: ${MAX_CLEANUP_DURATION_MINUTES} minutes (${MAX_DURATION_MS / 1000} seconds)`); | |
| Logger.log(`Folders Configured for Cleanup: ${FOLDERS_TO_CLEAN.join(', ')}`); | |
| Logger.log(`Senders to Delete: ${SENDERS_TO_DELETE.length > 0 ? SENDERS_TO_DELETE.join(', ') : 'All'}`); | |
| Logger.log(`Senders to Exclude: ${SENDERS_TO_EXCLUDE.length > 0 ? SENDERS_TO_EXCLUDE.join(', ') : 'None'}`); | |
| Logger.log(`Total Threads Identified for Deletion: ${totalThreadsProcessed}`); | |
| Logger.log(`Messages Identified for Deletion: ${messagesCollectedCount}`); | |
| Logger.log(`Deletion Attempted: ${deletionAttempted ? 'Yes' : 'No'}`); | |
| Logger.log(`Messages Successfully Deleted: ${messagesSuccessfullyDeletedCount}`); | |
| Logger.log(`Time Limit Reached During Execution: ${timeLimitHit ? 'Yes' : 'No'}`); | |
| Logger.log(`Actual Execution Duration: ${(Date.now() - startTime) / 1000} seconds`); | |
| Logger.log(`Status: ${deletionSuccessful ? 'SUCCESS' : (deletionAttempted && !deletionSuccessful ? 'FAILED' : 'NO_MESSAGES_TO_DELETE')}`); | |
| if (!deletionSuccessful && deletionErrorMessage !== "No error.") { | |
| Logger.log(`Error Details: ${deletionErrorMessage}`); | |
| } | |
| Logger.log("------------------------------------------"); | |
| } | |
| logSummary(); | |
| } |
@Aanusha-G , I recently considered the same idea for excluding senders. With a shared search mechanism, adding it was straightforward.
Below is the updated configuration required. Although I feel the search is faster at this point, you might also want to increase the MAX_CLEANUP_DURATION_MINUTES by a couple of minutes, too.
Gmail Cleanup Script Configuration
This script helps you automatically and permanently delete emails from your Gmail account based on specific criteria. You can customize the folders to clean, the senders to target for deletion, and the senders to always keep.
NOTE:
Keep in mind that Google will still age out and delete messages in your Trash and Spam folders as normal.
Here's a breakdown of the configuration settings:
Folders and Labels to Clean
const FOLDERS_TO_CLEAN = ["Trash", "Spam", "My Custom Label"];This array specifies which Gmail folders or labels the script will scan for messages to delete.
- The names must exactly match the labels in your Gmail account.
- For nested labels, use a forward slash
/(e.g.,"Projects/Subproject").
Senders to Delete
const SENDERS_TO_DELETE = ["unwanted.sender@example.com", "another.spam@domain.net"];This array lists the email addresses of senders whose messages you want to delete.
- The script will only delete emails from these specific addresses within the folders you've defined.
- If this array is empty, the script will delete messages from all senders in the specified folders.
Senders to Exclude
const SENDERS_TO_EXCLUDE = ["important.person@work.com", "do-not-touch@family.net"];This array defines a list of "safe" senders. The script will never delete messages from these email addresses, regardless of whether they are in the FOLDERS_TO_CLEAN or on the SENDERS_TO_DELETE list. This is a powerful safeguard to prevent accidental deletion of important emails.
Script Execution Time Limit
const MAX_CLEANUP_DURATION_MINUTES = 5;This setting ensures the script doesn’t run indefinitely by stopping it gracefully after the specified number of minutes.
Since Google Apps Script has a maximum execution time of 6 minutes per run, setting this above 6 minutes may lead to forced termination. It’s best to leave it at the default value to avoid hitting that limit.
Thank you for this! Would be lovely to have the option to delete from trash only emails from a specific sender, instead of the whole trash. But thanks for this, it makes my life so much better already!