Created
August 30, 2020 16:52
-
-
Save johnstanfield/7ab700eae63bd896c9c4e3083bcfc34e to your computer and use it in GitHub Desktop.
purge gmail when out of space
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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