Skip to content

Instantly share code, notes, and snippets.

Created January 8, 2017 16:39
Show Gist options
  • Star 73 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save anonymous/2cca33d376f7f924fdaa67891ad098cc to your computer and use it in GitHub Desktop.
Save anonymous/2cca33d376f7f924fdaa67891ad098cc to your computer and use it in GitHub Desktop.
function gmailAutoarchive() {
var delayDays = 2; // will only impact emails more than 48h old
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()-delayDays); // what was the date at that time?
// Get all the threads labelled 'autoarchive'
var label = GmailApp.getUserLabelByName("autoarchive");
var threads = label.getThreads(0, 400);
// we archive all the threads if they're unread AND older than the limit we set in delayDays
for (var i = 0; i < threads.length; i++) {
if (threads[i].getLastMessageDate()<maxDate)
{
threads[i].moveToArchive();
}
}
}
@mrdlcastle
Copy link

mrdlcastle commented Jul 6, 2018

Thanks for this, I tweaked it for my needs and it is available here
Archives any read message that is older than 24 hours.

@simon57nz
Copy link

I used a set of labels nested under a parent "autoarchive" and added the following into my fuction:

var labels = GmailApp.getUserLabels();
for (var a = 0; a < labels.length; a++) {
var curr_label = labels[a].getName();
var curr_label_parts = curr_label.split("/");
if (curr_label_parts[0] == "autoarchive") {
...// rest of archive function
}
}

@akamyshanov
Copy link

Or just leverage GMail's built in search features:

var threads = GmailApp.search("in:inbox label:auto-archive older_than:2d");

https://gist.github.com/akamyshanov/88e0bfa936296d14febe4cb7d5c37c78

@jaseinatl
Copy link

I would like to do something similar, but I only want threads that I have read. Is there a way to filter read messages?

@ukmercenary
Copy link

Cool script two questions first is this script safe as with respect it looks like we are giving permissions to a stranger on the internet!
Next, how do we set it to archive more than 400 older emails? I have going back to 2018 which need archiving.

@codeslubber
Copy link

Script runs for me, and then there are clearly items with the autoarchive tag that are older than 2d. What a joke.

@codeslubber
Copy link

Got this to work. The filter method suggested by @akamyshanov works. Wrote a single line in the script that applied the filter then output the match count. Then dropped into the loop and archived the ones that were found. The tools could be a lot better, jeez. ANyway thanks for this.

@superfawkes
Copy link

superfawkes commented Jun 30, 2019

Thank you! I've adapted it into a more generic cleanup script - the initial setup needs a bit of personal tweaking...
Edit - too many versions. I've added my gist here

@Al-Saqib
Copy link

Al-Saqib commented Jul 14, 2019

Thanks for this, I tweaked it for my needs and it is available here
Archives any read message that is older than 24 hours.

Hi mrdlcastle
Thank you for the tweaked version of the script .
However, shouldn't the last message be greater than max date? #14 of your script.

@superfawkes
Copy link

@CognitiveCaesar Messages more X days old is the same as date of message < today - X days.

@Al-Saqib
Copy link

@superfawkes thanks for clearing that up. My script was not working according to plan, so I thought that it might have something to do with the setup. However, once you pointed out the concept, I checked the trigger and found that its execution has failed for some reason. Still don't know why. But the script itself, once manually run, works fine.

@KamiinBlack
Copy link

I used a set of labels nested under a parent "autoarchive" and added the following into my fuction:

var labels = GmailApp.getUserLabels();
for (var a = 0; a < labels.length; a++) {
var curr_label = labels[a].getName();
var curr_label_parts = curr_label.split("/");
if (curr_label_parts[0] == "autoarchive") {
...// rest of archive function
}
}

If you have nested labels just use :
var threads = GmailApp.search("in:inbox label:label_parent-label_child1-label_child2"); ("-" -> use this as 'conector' between nested labels)

If you want to archive only read email add this code to condtition:
if (threads[i].isUnread()==false)

@dkim457
Copy link

dkim457 commented Oct 15, 2019

Is there a way to tweak this where it'll auto archive an email to a specific label, but only after it's been read by the user?

@KamiinBlack
Copy link

Is there a way to tweak this where it'll auto archive an email to a specific label, but only after it's been read by the user?

I have put this piece of additional cide in my previous post ( use function isUnread() ) ->
If you want to archive only read email add this code to condition:
if (threads[i].isUnread()==false)

@joshkadis
Copy link

joshkadis commented Apr 25, 2020

I definitely overthought by this by a lot! But here's a version with the option to set different cutoff days per label. (Note that it maxes at 100 threads and doesn't batch them.)

// Will be checked against lowercased label names
var autoarchiveLabels = {
  newsletters: 2
};

// Get cutoff date for a specific label
function labelDelayDate(labelName) {
  if (!autoarchiveLabels[labelName.toLowerCase()]) {
    return false;
  }
  var delayDays = autoarchiveLabels[labelName.toLowerCase()];
  var maxDate = new Date();
  maxDate.setDate(maxDate.getDate() - delayDays);
  return maxDate;
}

// Archive thread after cutoff dat
function shouldArchive(thread, label) {
  var maxDate = labelDelayDate(label.getName());
  if (!maxDate) {
    return false;
  }
  
  // Being in the inbox already is implicit but helps with logging
  // on the threads that are affected
  var shouldArchive = thread.getLastMessageDate() < maxDate && thread.isInInbox();

  if (shouldArchive) {
    Logger.log('Will archive: ' + thread.getFirstMessageSubject());
  }

  return shouldArchive;
}

// Check threads against cutoff date and archive them
function archiveLabel(label) {    
  Logger.log('Archiving ' + label.getName());
  var threads = label.getThreads(0, 100).filter(
    function (thread) { return shouldArchive(thread, label) }
  );
  Logger.log('Found ' + threads.length + ' archivable threads');
  if (threads.length) {
    GmailApp.moveThreadsToArchive(threads);
  }
}

// Find archivable labels
function gmailAutoarchive() {  
  var labels = GmailApp.getUserLabels();
  for (var i = 0; i < labels.length; i++) {
    var label = labels[i];
    if (Object.keys(autoarchiveLabels).indexOf(label.getName().toLowerCase()) !== -1) {
      archiveLabel(label);
    }
  }
}

https://gist.github.com/anonymous/2cca33d376f7f924fdaa67891ad098cc

@franprince
Copy link

franprince commented Sep 15, 2020

I slightly modified the original script because I needed to archive threads after a couple of hours.

function gmailAutoarchive() {
  var hours = 3600000;
  var days = 86400000;
  var delay = 4 * hours;  //Select quantity and time unit i.e. 7 days
  var maxDate = new Date();
  maxDate.setTime(maxDate.getTime()-delay); 

  var label = GmailApp.getUserLabelByName("autoarchive");
  if (label == null || label == undefined) return -1; 
  
  var threads = label.getThreads(0, 400).filter(function(thread) {
    // Only include threads older than the limit we set in delayDays
    return (thread.getLastMessageDate() < maxDate);
  });
  
  var batch_size = 100;
  while (threads.length) {
    var this_batch_size = Math.min(threads.length, batch_size);
    var this_batch = threads.splice(0, this_batch_size);
    GmailApp.moveThreadsToArchive(this_batch);
  }
}

@jututt
Copy link

jututt commented Nov 18, 2020

Here's my version taking care of all inbox email, irrespective of the label

function gmailAutoarchive() {
  
  var delayDays = 3; // only impact emails older than 3 days
  var maxDate = new Date();
  maxDate.setDate(maxDate.getDate()-delayDays); // what was the date at that time?

  // Get all inbox threads
  var threads = GmailApp.getInboxThreads();
  
  // archive all the threads older than the limit set in delayDays
  for (var i = 0; i < threads.length; i++) {
    if (threads[i].getLastMessageDate()<maxDate)
    {
      threads[i].moveToArchive();
    }
  }
}

@ChristiaanScheermeijer
Copy link

A small addition to @jututt's version, this will not auto archive "starred" and "important" threads:

function gmailAutoarchive() {
  
  var delayDays = 3; // only impact emails older than 3 days
  var maxDate = new Date();
  maxDate.setDate(maxDate.getDate()-delayDays); // what was the date at that time?

  // Get all inbox threads
  var threads = GmailApp.getInboxThreads();
  
  // archive all the threads older than the limit set in delayDays which are not marked as imported or have starred messages
  for (var i = 0; i < threads.length; i++) {
    if (threads[i].getLastMessageDate()<maxDate && !threads[i].isImportant() && !threads[i].hasStarredMessages()) {
      threads[i].moveToArchive();
    }
  }
}

@matthewoden
Copy link

Has anyone run into an issue where you have to reauthenticate weekly?

@dancapper
Copy link

Hi all, after playing around with this I came up with a more efficient version which uses search to find all affected threads instead of iterating through threads belonging to the label. Hope it helps someone.

Replace moveThreadsToArchive with moveThreadsToTrash if you want to trash the threads instead.

function gmailAutoarchive() {
  
  var rules = { // Each label with number of days to keep
    "billsbillsbills" : 2,
    "newslettersandstuff" : 28
  }

  var batch_size = 100;

  for (let label in rules) {
    
    var keepdays = rules[label];
  
    Logger.log(`Archiving all threads in ${label} older than ${keepdays} Days`);

    var threads = GmailApp.search(`label:${label} older-than:${keepdays}d`);

    Logger.log(`Identified ${threads.length.toString()} threads for archival in ${label}`);

    while (threads.length) {
      var this_batch_size = Math.min(threads.length, batch_size);
      var this_batch = threads.splice(0, this_batch_size);
      GmailApp.moveThreadsToArchive(this_batch);
    }
  }
}

@BLiTyvr
Copy link

BLiTyvr commented Jul 17, 2021

Hi all, after playing around with this I came up with a more efficient version which uses search to find all affected threads instead of iterating through threads belonging to the label. Hope it helps someone.

Replace moveThreadsToArchive with moveThreadsToTrash if you want to trash the threads instead.

function gmailAutoarchive() {
  
  var rules = { // Each label with number of days to keep
    "billsbillsbills" : 2,
    "newslettersandstuff" : 28
  }

  var batch_size = 100;

  for (let label in rules) {
    
    var keepdays = rules[label];
  
    Logger.log(`Archiving all threads in ${label} older than ${keepdays} Days`);

    var threads = GmailApp.search(`label:${label} older-than:${keepdays}d`);

    Logger.log(`Identified ${threads.length.toString()} threads for archival in ${label}`);

    while (threads.length) {
      var this_batch_size = Math.min(threads.length, batch_size);
      var this_batch = threads.splice(0, this_batch_size);
      GmailApp.moveThreadsToArchive(this_batch);
    }
  }
}

Note that the search operator is older_than: not older-than:
per https://support.google.com/mail/answer/7190?hl=en

Otherwise, this code works well. :) Thanks @dancapper

@dancapper
Copy link

Thanks @BLiTyvr - quite right. I fixed this in my code when I noticed it wasn't working, but forgot to come back and update my comment.

You can find my final version at https://github.com/dancapper/gmailArchiveScript/ if it's a help to anyone, I made it easier to update the rules to suit your needs, and set a flag to archive or trash the matching threads.

@maheshmnj
Copy link

Hey, can someone please tell me does labelling an email would move it from the inbox?
Let's say I am getting emails from a particular email everyday email@example.com, I would like to keep them under the label example and don't want to see them in my inbox.

@franprince
Copy link

franprince commented Aug 25, 2021

Hey, can someone please tell me does labelling an email would move it from the inbox?
Let's say I am getting emails from a particular email everyday email@example.com, I would like to keep them under the label example and don't want to see them in my inbox.

You can do that using filters on Gmail, no need for a script. Just adding a label won't move it from the inbox, you need to archive it too.
https://support.google.com/mail/answer/6579?hl=en#zippy=%2Ccreate-a-filter

@maheshmnj
Copy link

maheshmnj commented Aug 26, 2021

Thanks, @fanprince its working beautifully.

@giftedsiege
Copy link

do you know if this impact snoozed emails? (let's say an email that older than 2 days that has been snoozed to reappear in two weeks)

@blhoward2
Copy link

blhoward2 commented Apr 22, 2023

Hi all, after playing around with this I came up with a more efficient version which uses search to find all affected threads instead of iterating through threads belonging to the label. Hope it helps someone.

Replace moveThreadsToArchive with moveThreadsToTrash if you want to trash the threads instead.

function gmailAutoarchive() {
  
  var rules = { // Each label with number of days to keep
    "billsbillsbills" : 2,
    "newslettersandstuff" : 28
  }

  var batch_size = 100;

  for (let label in rules) {
    
    var keepdays = rules[label];
  
    Logger.log(`Archiving all threads in ${label} older than ${keepdays} Days`);

    var threads = GmailApp.search(`label:inbox label:${label} older-than:${keepdays}d`);

    Logger.log(`Identified ${threads.length.toString()} threads for archival in ${label}`);

    while (threads.length) {
      var this_batch_size = Math.min(threads.length, batch_size);
      var this_batch = threads.splice(0, this_batch_size);
      GmailApp.markThreadsRead(this_batch);
      GmailApp.moveThreadsToArchive(this_batch);
    }
  }
}

I know this is very old, but if anyone else finds this you're actually reprocessing all of the archived emails every time. Adding label:inbox limits the search to the emails not already archived. I've modified the above to do that, and also to mark the messages as read while moving them.

@Avocadososemix
Copy link

Thank you for the solutions everyone. I had to change older-than to older_than in @blhoward2's solution and it worked perfectly.

function gmailAutoarchive() {
  
  var rules = { // Each label with number of days to keep
    "autoarchive" : 2,
    "newslettersandstuff" : 28
  }

  var batch_size = 100;

  for (let label in rules) {
    
    var keepdays = rules[label];
    Logger.log(`Archiving all threads in ${label} older than ${keepdays} Days`);

    var threads = GmailApp.search(`label:inbox label:${label} older_than:${keepdays}d`);

    Logger.log(`Identified ${threads.length.toString()} threads for archival in ${label}`);

    while (threads.length) {
      var this_batch_size = Math.min(threads.length, batch_size);
      var this_batch = threads.splice(0, this_batch_size);
      GmailApp.markThreadsRead(this_batch);
      GmailApp.moveThreadsToArchive(this_batch);
    }
  }
}

@101legend101
Copy link

Hey, i am looking to archive all my "read" mails which have "user labels" after 2 days, can anyone help with that?. i want to do it for all mails user labels instead of doing individually for all the labels i have. i also do not want to create a separate label to use as an archived inbox if possible. if not i will go this way

@bo33b
Copy link

bo33b commented Feb 21, 2024

@101legend101 this is my approach, quite simple really. Cheers.

function gmailAutoarchive() {

  // Build the query
  var query = "in:inbox is:read has:userlabels older_than:2d";
  
  // Get the threads
  var threads = GmailApp.search(query);
  
  // Archive the threads
  for (var thread of threads) thread.moveToArchive();

}

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