Skip to content

Instantly share code, notes, and snippets.

@thaithcock
Forked from jamesramsay/README.md
Last active February 19, 2024 03:16
Show Gist options
  • Select an option

  • Save thaithcock/8ac3c45a322ab88bb71a3984b8d2174f to your computer and use it in GitHub Desktop.

Select an option

Save thaithcock/8ac3c45a322ab88bb71a3984b8d2174f to your computer and use it in GitHub Desktop.
Gmail: delete old emails automatically

Gmail: delete old emails automatically

Automatically deletes old emails that match the specified label.

Get started

  • Create a new Google Apps Script at https://script.google.com
  • Overwrite the placeholder with the javascript below
  • Update the following constants:
    • LABEL_TO_DELETE: the label that should be have old messages deleted
    • DELETE_AFTER_DAYS: the age of messsages after which they will be moved to trash
    • DAILY_RUN_HOUR: what hour you want the script to run at
  • Save the script, then run:
    • Install

If you ever want to remove the script, run Uninstall to remove any left over triggers.

Acknowledgements

/** The name of the Gmail Label that is to be checked for purging */
const LABELS_TO_DELETE = [
"auto_delete"
];
/** Labels to never delete */
const LABELS_TO_NOT_DELETE = [
"do_not_delete"
]
const TRIGGER_NAME = "dailyDeleteGmail";
/** Purge messages in the above label automatically after how many days? */
const DELETE_AFTER_DAYS = "30";
/** Maximum number of threads to process per run */
const PAGE_SIZE = 300;
/** If number of threads exceeds page size, resume job after X mins (max execution time is 6 mins) */
const RESUME_FREQUENCY = 15;
/** what hour to run the daily trigger at */
const DAILY_RUN_HOUR = 10;
/**
* Creates an initial trigger to run the project,
* subsequent runs are automatically created
*/
function Install() {
// First run 1 minute after install
console.log("In Install, creating trigger to run after 1 minute");
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased()
.after(1000*60*1)
.create();
}
/**
* Removes any lingering triggers.
* During normal execution new triggers are created,
* To stop/remove this project, run this manually
*/
function Uninstall() {
const triggers = ScriptApp.getProjectTriggers();
console.log(`Found ${triggers.length} triggers to remove`);
triggers.forEach(trigger => {
ScriptApp.deleteTrigger(trigger);
})
}
function dailyDeleteGmail(ev) {
console.log(`Running for ${Session.getActiveUser().getEmail() ?? "unknown"}`);
const labels = LABELS_TO_DELETE.map(label => `label:${label}`).join(" OR ");
const not_labels = LABELS_TO_NOT_DELETE.map(label => `label:${label}`).join(" OR ");
const search = `(${labels}) NOT (${not_labels}) older_than:${DELETE_AFTER_DAYS}d`;
console.log(`search query: ${search}`);
try {
Uninstall();
const threads = GmailApp.search(search, 0, PAGE_SIZE);
if (threads.length === PAGE_SIZE) {
const followupTime = 1000*60*RESUME_FREQUENCY;
console.log(`More to do, scheduling a followup trigger to run after ${RESUME_FREQUENCY} minutes`);
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased()
.after(followupTime)
.create();
} else {
console.log("Caught up, creating a followup trigger for tomorrow.");
const nextRunTime = new Date();
nextRunTime.setDate(nextRunTime.getDate() + 1);
nextRunTime.setHours(DAILY_RUN_HOUR);
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased()
.at(nextRunTime)
.create();
}
console.log("Processing " + threads.length + " threads...");
const age = new Date();
age.setDate(age.getDate() - DELETE_AFTER_DAYS);
let deleted = 0;
threads.forEach(thread => {
if (thread.getLastMessageDate() < age) {
thread.moveToTrash();
deleted += thread.getMessageCount();
} else {
const messages = GmailApp.getMessagesForThread(thread);
messages.forEach(email => {
if (email.getDate() < age) {
email.moveToTrash();
deleted++
}
})
}
})
console.log(`Run completed and moved ${deleted} mails to trash.`)
} catch (e) {
console.error(e);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment