Skip to content

Instantly share code, notes, and snippets.

@johnstanfield
Created August 30, 2020 16:52
Show Gist options
  • Save johnstanfield/7ab700eae63bd896c9c4e3083bcfc34e to your computer and use it in GitHub Desktop.
Save johnstanfield/7ab700eae63bd896c9c4e3083bcfc34e to your computer and use it in GitHub Desktop.
purge gmail when out of space
// purge gmail script
// i've been using this for years to keep gmail from going over the limit
// it has gotten me from 99% to 50% many times on various accounts
//
// it runs on google apps script, which is google's script platform that can access your email
// to automatically delete older messages according to the rules below
//
// it's controlled by the CONFIG array
// set an age (required)
// set a label or from (one of them is required)
// messages will be searched by label or from address, and messages older than age will be deleted
// they will be deleted in chunks of CHUNK_SIZE and (if you run the Install function) the purge will be run every INTERVAL_MINUTES
//
//
// set the CONFIG variable
// then run the purgeGmail function
// then check your GMail trash and/or View => Logs
// when you're happy with the CONFIG, run the Install function
//
//
// adapted from https://ctrlq.org/code/19383-bulk-delete-gmail
var CONFIG = [
{"age": "90", "label":"coupons/offers"},
{"age": "600", "from":"noreply"},
{"age": "600", "from":"no-reply"},
{"age": "600", "from":"donotreply"}
];
// this is how often to run the purge, in minutes
var INTERVAL_MINUTES = 5;
// the number of messages to search for and delete each time the script is run
// sometimes Google gives you errors related to resources consumed. 100 usually works if CONFIG has a couple items. lowering this may help stop that error.
var CHUNK_SIZE = 100;
// sometimes Google gives you errors related to resources consumed.
// at one point, sleeping for 100 to 500 millseconds helped stop that error
var SLEEP_BETWEEN_DELETES = 100;
// sometimes Google gives you errors related to resources consumed.
// at one point, exiting if messages were deleted by one rule helped stop that error
// i.e. if the first rule returns messages, exit. otherwise try second rule
var BREAK_LOOP_IF_MESSAGES_FOUND = false;
function Install() {
// delete all triggers
// then set a weekly trigger to reinstall to ensure it is always running
// then set a minutes trigger to purge on an ongoing basis
deleteAllTriggers();
var weeklyTrigger = ScriptApp.newTrigger("Install")
.timeBased().onWeekDay(ScriptApp.WeekDay.MONDAY).atHour(0).create();
Logger.log("created weekly install trigger: " + weeklyTrigger.getUniqueId());
var minutesTrigger = ScriptApp.newTrigger("purgeGmail")
.timeBased().everyMinutes(INTERVAL_MINUTES).create();
Logger.log("created " + INTERVAL_MINUTES + "-minute purge trigger: " + minutesTrigger.getUniqueId());
}
function Uninstall() {
deleteAllTriggers();
}
function deleteAllTriggers() {
// Locate a trigger by unique ID
var allTriggers = ScriptApp.getProjectTriggers();
// Loop over all triggers
for (var i = 0; i < allTriggers.length; i++) {
var triggerId = allTriggers[i].getUniqueId();
Logger.log("deleting trigger: " + triggerId);
ScriptApp.deleteTrigger(allTriggers[i]);
}
}
function purgeGmail() {
Logger.log("started");
var totalDeleted = 0;
// Loop over the configuration
for (var i = 0; i < CONFIG.length; i++) {
var item = CONFIG[i];
var age = new Date();
age.setDate(age.getDate() - item.age);
var purge = Utilities.formatDate(age, "GMT", "yyyy-MM-dd");
var search = "";
if (item.hasOwnProperty('age')) {
if (item.hasOwnProperty('label')) {
search += " label:" + item.label;
} else if (item.hasOwnProperty('from')) {
search += " from:" + item.from;
} else {
Logger.log("could not understand this item. 'age' is required. either 'label' or 'from' must be specified: " + JSON.stringify(item));
continue;
}
search += " before:" + purge;
} else {
Logger.log("could not understand this item. 'age' is required. either 'label' or 'from' must be specified: " + JSON.stringify(item));
continue;
}
Logger.log("going to look for emails using: " + search);
var threads = GmailApp.search(search, 0, CHUNK_SIZE);
Logger.log("searched and found: " + threads.length);
// if anything was deleted, break the loop to reduce resources
// eventually it will be zero, and the next one can be checked
// eventually they will all be purged (it can take days or weeks if there are GBs of emails)
for (var t=0; t<threads.length; t++) {
var messages = GmailApp.getMessagesForThread(threads[t]);
if(messages != null && messages.length>0){
var email = messages[0];
if (email.getDate() < age) {
Logger.log("moved to trash: " + email.getSubject().substring(0,15) + '... dated ' + Utilities.formatDate(age, email.getDate(), "yyyy-MM-dd"));
threads[t].moveToTrash();
totalDeleted++;
}
}
Utilities.sleep(SLEEP_BETWEEN_DELETES);
}
if (BREAK_LOOP_IF_MESSAGES_FOUND == true && threads.length > 0) {
Logger.log("going to exit now to save resources");
break;
} else if (i < CONFIG.length-1) {
Logger.log("going to continue");
}
}
Logger.log("finished. " + totalDeleted + " messages deleted");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment