Skip to content

Instantly share code, notes, and snippets.

@johannrichard
Last active July 17, 2023 21:27
Show Gist options
  • Save johannrichard/bf16d81a60dfbfff110d0824f2cdde87 to your computer and use it in GitHub Desktop.
Save johannrichard/bf16d81a60dfbfff110d0824f2cdde87 to your computer and use it in GitHub Desktop.
E-Mail Retention Policies for Gmail

How to bring E-Mail retention policies to Gmail / Google Mail:

  • Go to Google Scripts and create a blank project (make sure you are logged into your Google account);
  • paste the code (below) (and modify the policies as needed);
  • set a trigger (Resources -> Current Project's Triggers -> Add one now) to run it at the preferred interval; and
  • create filters in Gmail/Google Mail that set policies when specific messages arrive

Inspired and adapted from Gmail Automation: 5 Useful Google Scripts to Automate Your Gmail

/****
* This Script will apply different e-mail policies according to a defined set of labels
* Actions:
* - Delete: will delete (move) the message threa to the trash (unless starred)
* - Archive: will move the thread to the archive
*
* New policies: To add a new policy, add a new entry in the "policies" map
*
* When executing the action, the corresponding label will be removed. This will speed up the
* processing of messages considerably (otherwise, the messages would be reprocessed on every run).
* Starred messages will not be deleted.
*
* By setting a timed trigger, you can execute the script in regular intervals (e.g. every 30 minutes)
* Create a filter that will apply a specific label automatically to the filtered mail and
* your mailbox will unclutter itself automatically.
*
* Inspired/adapted from https://www.maketecheasier.com/google-scripts-to-automate-gmail/
*/
function applyEmailPolicy() {
var policies = {
// Archive Policies
"monthArchive": { "label": "Archive After 30 Days", days: 30, action: "archive" },
"weekArchive": { "label": "Archive After 1 Week", days: 7, action: "archive"},
"biWeeklyArchive": { "label": "Archive After 2 Weeks", days: 14, action: "archive"},
// Delete Policiess
"monthDelete": { "label": "Delete After 30 Days", days: 30, action: "delete" },
"yearDelete": { "label": "Delete After 1 Year", days: 365, action: "delete"},
"decadeDelete": { "label": "Delete After 10 Years", days: 3650, action: "delete"},
}
for (var policyKey in policies) {
var policy = policies[policyKey];
Logger.log("Applying E-Mail Policy '" + policy["label"] + "'");
var label = GmailApp.getUserLabelByName(policy["label"]);
if(label == null){
GmailApp.createLabel(policy["label"]);
} else {
var delayDays = policy["days"];
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()-delayDays);
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
if (threads[i].getLastMessageDate()<maxDate){
switch(policy["action"]) {
case "delete":
if(!threads[i].hasStarredMessages()) {
Logger.log("Deleting Thread '" + threads[i].getFirstMessageSubject() + "'");
threads[i].removeLabel(label);
threads[i].moveToTrash();
} else {
Logger.log("Skipping Thread '" + threads[i].getFirstMessageSubject() + "'");
}
break;
case "archive":
Logger.log("Archiving Thread '" + threads[i].getFirstMessageSubject() + "'");
threads[i].removeLabel(label);
threads[i].moveToArchive();
break;
}
}
}
}
}
}
@rafitadiaz
Copy link

Please notice that the script won't work if you already have a big bulk of emails or you get too many emails with the same label because the method label.getThreads(); only returns the first 500 emails for this label.

This means that if you have let's say 10000 emails, and in the first 500 there is no email with date > MaxDate the script simply won't remove any email.

I solved this by adding ranges and going from the max to the min parsing the dates from all of them (in my case check the first 5000 emails was enough.)

        maxDate.setDate(maxDate.getDate()-delayDays);

      minThreadIndex = 4500
      while(minThreadIndex >= 0) {

        // Get The emails in batches of 500: [4500-5000, 4000-4500.... 0-500]                
        var threads = label.getThreads(minThreadIndex,500);

        Logger.log("Processing " + threads.length + " threads. Index[" + minThreadIndex + "]")
        for (var i = 0; i < threads.length; i++) {
          if (threads[i].getLastMessageDate()<maxDate){  
            switch(policy["action"]) {
              case "delete":
                if(!threads[i].hasStarredMessages()) {
                  Logger.log("Deleting Thread '" + threads[i].getFirstMessageSubject() + "'");
                  threads[i].removeLabel(label);
                  threads[i].moveToTrash();
                } else {
                  Logger.log("Skipping Thread '" + threads[i].getFirstMessageSubject() + "'");
                }
                break;
              case "archive":
                Logger.log("Archiving Thread '" + threads[i].getFirstMessageSubject() + "'");
                threads[i].removeLabel(label);
                threads[i].moveToArchive();
                break;
            }
          } 
        }
        minThreadIndex = minThreadIndex - 500;
      }

@rafitadiaz
Copy link

And also thanks for sharing this script, it saved my life!!! 🙏

@johannrichard
Copy link
Author

Thanks for the comment and sharing your workaround: You’re very welcome. I’m still puzzled by the fact that such a feature is not standard in mail services.

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