Skip to content

Instantly share code, notes, and snippets.

@kelnos
Created February 10, 2021 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kelnos/100b1af165a6b6cdaf01dbd53a5483a4 to your computer and use it in GitHub Desktop.
Save kelnos/100b1af165a6b6cdaf01dbd53a5483a4 to your computer and use it in GitHub Desktop.
GMail Auto-Purge Script
// The name of the Gmail labels and categories that are to be auto-purged
var GMAIL_LOCATIONS = {
"label": [
"<some-label>"
],
"category": [
"promotions"
]
};
// Purge messages automatically after how many days?
var PURGE_AFTER = 60;
// Max to purge in one go
var PURGE_LIMIT = 100;
// If more than PURGE_LIMIT mails to purge, when to schedule the next purge (minutes)
var PURGE_RESCHEDULE_AFTER = 10;
// Email address to send error/debug logs to
var LOG_EMAIL = "<some-email-here>";
// Set to true to always email the execution log
var DEBUG_EMAIL = false;
// How we identify the last trigger set
var LAST_TRIGGER_ID = "GMAIL_AUTO_PURGE_LAST_TRIGGER_ID";
function purgeGmail() {
var age = new Date();
age.setDate(age.getDate() - PURGE_AFTER);
var purge = Utilities.formatDate(age, Session.getTimeZone(), "yyyy-MM-dd");
var threads = [];
try {
// We are processing a max of PURGE_LIMIT messages in a batch to prevent script errors,
// else it may throw an Exceeded Maximum Execution Time exception.
for (location in GMAIL_LOCATIONS) {
for (var i = 0; i < GMAIL_LOCATIONS[location].length; ++i) {
if (PURGE_LIMIT - threads.length > 0) {
var search = location + ": " + GMAIL_LOCATIONS[location][i] + " before:" + purge;
threads = threads.concat(GmailApp.search(search, 0, PURGE_LIMIT - threads.length));
}
}
}
Logger.log("Got " + threads.length + " threads to delete");
try {
// Attempt to clean up the last one-off trigger, since Google won't, and
// there is a limit on the number of (even expired) triggers you can have.
var lastTriggerId = PropertiesService.getUserProperties().getProperty(LAST_TRIGGER_ID);
if (lastTriggerId != null) {
Logger.info('Got last trigger ID to delete: ' + lastTriggerId);
var allTriggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < allTriggers.length; ++i) {
if (allTriggers[i].getUniqueId() == lastTriggerId) {
Logger.info('Deleting trigger');
ScriptApp.deleteTrigger(allTriggers[i]);
break;
}
}
}
} catch (e) {
Logger.log('Failed to fetch/delete last trigger; continuing: ' + e);
}
// For large batches, create another time-based trigger that will
// activate the auto-purge process after PURGE_RESCHEDULE_AFTER minutes.
if (threads.length == PURGE_LIMIT) {
var trigger = ScriptApp.newTrigger("purgeGmail")
.timeBased()
.after(1000 * 60 * PURGE_RESCHEDULE_AFTER)
.create();
PropertiesService.getUserProperties().setProperty(LAST_TRIGGER_ID, trigger.getUniqueId());
}
// An email thread may have multiple messages and the timestamp of
// individual messages can be different.
var nDeleted = 0;
for (var i = 0; i < threads.length; i++) {
Logger.log("Processing thread " + i+1);
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0; j < messages.length; j++) {
Logger.log("Deleting message " + j+1);
var email = messages[j];
if (email.getDate() < age) {
email.moveToTrash();
nDeleted += 1;
}
}
}
Logger.log('Purge complete for ' + nDeleted + ' messages');
if (DEBUG_EMAIL && LOG_EMAIL) {
GmailApp.sendEmail(LOG_EMAIL, "GMail Auto Purge Debug Logs", Logger.getLog());
}
} catch (e) {
// If the script fails for some reason or catches an exception,
// it will simply defer auto-purge until the next run.
Logger.log("Failed to complete purge: " + e);
if (LOG_EMAIL) {
GmailApp.sendEmail(LOG_EMAIL, "GMail Auto Purge Error Logs", Logger.getLog());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment