Skip to content

Instantly share code, notes, and snippets.

@benbjurstrom
Last active May 18, 2023 00:12
Embed
What would you like to do?
PurgeOldEmails

PurgeOldEmails

A Google Apps Script script to automatically delete unarchived mail after 7 days that hasn't been starred or marked as important

Quick Start

  1. Backup your emails using Google Takeout.
  2. Load this script into a new Google Apps Script project.
  3. Execute the setPurgeTrigger() function to set a trigger that will call the purge() function every day.

A detailed blog post with more information can be found at https://benbjurstrom.com/purge-email

Acknowledgements

Thanks to this gist by jamesramsay for getting me started in the right direction.

/*
|--------------------------------------------------------------------------
| PurgeOldEmails
|--------------------------------------------------------------------------
| https://gist.github.com/benbjurstrom/00cdfdb24e39c59c124e812d5effa39a
|
*/
// Purge messages automatically after how many days?
var DELETE_AFTER_DAYS = 7
// Maximum number of message threads to process per run.
var PAGE_SIZE = 150
/**
* Create a trigger that executes the purge function every day.
* Execute this function to install the script.
*/
function setPurgeTrigger() {
ScriptApp
.newTrigger('purge')
.timeBased()
.everyDays(1)
.create()
}
/**
* Create a trigger that executes the purgeMore function two minutes from now
*/
function setPurgeMoreTrigger(){
ScriptApp.newTrigger('purgeMore')
.timeBased()
.at(new Date((new Date()).getTime() + 1000 * 60 * 2))
.create()
}
/**
* Deletes all triggers that call the purgeMore function.
*/
function removePurgeMoreTriggers(){
var triggers = ScriptApp.getProjectTriggers()
for (var i = 0; i < triggers.length; i++) {
var trigger = triggers[i]
if(trigger.getHandlerFunction() === 'purgeMore'){
ScriptApp.deleteTrigger(trigger)
}
}
}
/**
* Deletes all of the project's triggers
* Execute this function to unintstall the script.
*/
function removeAllTriggers() {
var triggers = ScriptApp.getProjectTriggers()
for (var i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i])
}
}
/**
* Wrapper for the purge function
*/
function purgeMore() {
purge()
}
/**
* Deletes any emails from the inbox that are more then 7 days old
* and not starred or marked as important.
*/
function purge() {
removePurgeMoreTriggers()
var search = 'in:inbox -in:starred -in:important older_than:' + DELETE_AFTER_DAYS + 'd'
var threads = GmailApp.search(search, 0, PAGE_SIZE)
if (threads.length === PAGE_SIZE) {
console.log('PAGE_SIZE exceeded. Setting a trigger to call the purgeMore function in 2 minutes.')
setPurgeMoreTrigger()
}
console.log('Processing ' + threads.length + ' threads...')
var cutoff = new Date()
cutoff.setDate(cutoff.getDate() - DELETE_AFTER_DAYS)
// For each thread matching our search
for (var i = 0; i < threads.length; i++) {
var thread = threads[i]
// Only delete if the newest message in the thread is older then DELETE_AFTER_DAYS
if (thread.getLastMessageDate() < cutoff) {
thread.moveToTrash();
}
}
}
@sat2493
Copy link

sat2493 commented Oct 26, 2020

Thank you for sharing this code! :)

@blackstatic42
Copy link

Is their somehow to make it skip by labeled messages as well? Any insight would be greatly appreciated.

@aaronsomek
Copy link

I noticed that the script was picking up important and starred emails. Perhaps Gmail has updated their label parameters.
In line 76 I changed in:inbox -in:starred -in:important to -in:sent -is:starred -is:important
This searches ALL my mail - even archived, and doesn't grab any starred or important threads.

@loeasy68
Copy link

Thanks for sharing this code and really like your video on Youtube. Kindly share some tips and video for learning Automation testing.

I agree

@jacendvs
Copy link

jacendvs commented Oct 30, 2021

I searched for something like this because the search parameter "older_than" was not working. After I completed the script setup, the script was not working, I removed the parameter "older_than" and the script started running the Purge More automatically, the way it should.

This is unfortunate, and I dont know how to get around this problem.

edit: actually, the script might not be running automatically. :sigh:

update:

It is running .... but with the fact that I cant search "older_than" or something... im stuck.

image

@mmck345
Copy link

mmck345 commented Nov 24, 2021

Thanks for sharing the code and blog with the detailed video! 👍

@mmck345
Copy link

mmck345 commented Nov 25, 2021

image

Does anyone have any idea why this is happening?

@el-el22
Copy link

el-el22 commented May 19, 2022

Hi Ben,

Do you have a google app script that gets the unregistered emails in my Gmail inbox and extract the email address and its content and generate it to a text file or to a google spreadsheet automatically.

For example, 123@XYZ.com is an unregistered email in my gmail and this email contains the following content 112233445566. And the generated Text file for example should be like:

123@XYZ.com 112233445566

Ben, is it possible for me to do this, I would really appreciate your help on this.

My email: el.el86@outlook.com

Best regards,

@JacobTr97
Copy link

Hi, My code is running only twice and doesn't trigger again after 2 mins. May I know what can be done?

Thank you.

chrome_4NjUtKWpfI

Same problem... Anyone have a solution for this? Would be greatly appreciated.

@jtlarson
Copy link

Ben--thanks for this!

@blackstatic42

Is their somehow to make it skip by labeled messages as well? Any insight would be greatly appreciated.

I think every message in gmail is 'labeled' with at least a folder label, so omitting them would be effectively omitting ALL messages. You could probably skip specific labels like this

Add your label list near the top like this:
// Purge messages with these labels: var LABELS_TO_SAVE = [ "mailinglist", "Updates", "Social", "Promotions" ];

Then change line 76 (starts with 'var search') to this:
var search = "(-label:" + LABELS_TO_SAVE.join(" OR -label:") + ") in:inbox -in:starred -in:important older_than:" + DELETE_AFTER_DAYS + 'd'

You can also make this a list of labels to delete--just rename the var to "LABELS_TO_DELETE" in both places for clarity, and remove the "-" before both 'label:' entries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment