casolorz
casolorz

Reputation: 9554

What am I doing wrong when triggering a Gmail script to run again after the timeout?

I'm trying to clear an account of emails on Gmail. Doing it on the Gmail UI leads to errors probably because there are over 500k emails.

So I've started doing it with the Apps Script website https://script.google.com/ based on some scripts I have found and it works fine until around five or six minutes when it times out.

Right now the way I have it setup (code below), it runs fine but when it hits isTimeUp it just exits. The newTrigger is never running.

function myFunction() {
  console.log("myFunction")
  var batchSize = 100
  var today = new Date();
  while (true) {

    var threads = GmailApp.search('before:2020/05/20');
    for (j = 0; j < threads.length; j += batchSize) {
      console.log("Batch " + j)
      GmailApp.moveThreadsToTrash(threads.slice(j, j + batchSize));

    }
    if (isTimeUp(today)) {
      console.log("time up")
      var triggers = ScriptApp.getProjectTriggers();
      try {
        ScriptApp.deleteTrigger(triggers[0]);
      } catch (e) {

      }
      ScriptApp.newTrigger("myFunction")
        .timeBased()
        .after(1000)
        .create();
      break;
    }
  }
}


function isTimeUp(today) {
  var now = new Date();
  return now.getTime() - today.getTime() > 300000;

}

This is the log I see:

4:46:05 PM  Notice  Execution started
4:46:05 PM  Info    myFunction
4:46:06 PM  Info    Batch 0
4:46:19 PM  Info    Batch 100
4:46:32 PM  Info    Batch 200
4:46:45 PM  Info    Batch 300
4:46:58 PM  Info    Batch 400
4:47:11 PM  Info    Batch 0
4:47:23 PM  Info    Batch 100
4:47:37 PM  Info    Batch 200
4:47:49 PM  Info    Batch 300
4:48:01 PM  Info    Batch 400
4:48:14 PM  Info    Batch 0
4:48:28 PM  Info    Batch 100
4:48:40 PM  Info    Batch 200
4:48:53 PM  Info    Batch 300
4:49:05 PM  Info    Batch 400
4:49:18 PM  Info    Batch 0
4:49:31 PM  Info    Batch 100
4:49:43 PM  Info    Batch 200
4:49:58 PM  Info    Batch 300
4:50:18 PM  Info    Batch 400
4:50:33 PM  Info    Batch 0
4:50:46 PM  Info    Batch 100
4:50:59 PM  Info    Batch 200
4:51:12 PM  Info    Batch 300
4:51:26 PM  Info    Batch 400
4:51:39 PM  Info    time up
4:51:39 PM  Notice  Execution completed

What am I doing wrong?

Upvotes: 0

Views: 344

Answers (2)

Wicket
Wicket

Reputation: 38254

Taking a second look to the code and based on the comments, the problem looks to be related to have consumed the daily trigger execution time quota, but there is no error message because the catch (e) code block is empty. In order to make the script log the error message, replace

      } catch (e) {

      }

by

      } catch (e) {
        console.error(e.message, e.stack);
      }

Based on my own experience using after method of the Google Apps Script trigger builder, I think that 1000 milliseconds is a too small value. Try using something equal or greater than 60000 milliseconds (1 minute).


Considering that you want to process a very large number of messages, please bear in mind that:

  1. Google Apps Script has daily trigger total runtime quota, at the time of writing this the quotas are 90 minutes for free accounts, 6 hours for Google Workspace accounts. For the current quotas please checkout https://developers.google.com/apps-script/guides/services/quotas.
  2. GmailApp.search(query) might fail when there are too many threads (ref. search(query)). Instead of this method use search(query, start, max).

Also please bear in mind that Google Apps Script services are slow. If you found the use of GmailApp be too slow,

  1. try increasing the batch size (up to 500)
  2. try using the Advanced Gmail Service

If you found that it is still too slow and that you are exceeding the quotas you might try to use the Gmail API through the Url Fetch Service (Class UrlFetchApp). For this you should create a Google Cloud Project and set a billing method.

If you prefer to keep using the GmailApp or the Gmail (Advanced Gmail Service), you might create time-driven triggers to run at specific time for several days to initiate your myFunction or run it manually until you find that all the corresponding threads were trashed.

Related

Upvotes: 1

Cooper
Cooper

Reputation: 64082

Try this:

function removeAllThreads() {
  Gmail.Users.Threads.list("me").threads.map(t => t.id).forEach(id => Gmail.Users.Threads.remove("me",id))
}

Upvotes: 1

Related Questions