1

我遇到了 gmail 的各种速率限制,我不确定我能做些什么来解决它们。我想要完成的是在 gmail 中搜索任何带有某些“过期”标签的消息(以分钟为单位的不同时间)。我的意图是让邮件规则将这些标签应用于在一定时间后变得无关紧要的邮件。我希望这些邮件保留在我的收件箱中,直到它们过期,然后自动存档。我基于我在http://googleappsdeveloper.blogspot.com/2011/07/gmail-snooze-with-apps-script.html看到的一篇文章的一般技术

我在每五分钟运行一次“过期”功能的触发器上有这个。

因此,它每五分钟调用 10 次 GmailApp.getUserLabelByName 和 1 次 getThreads()。然后根据它找到多少匹配线程,对于每个线程:

1 x getFirstMessageSubject 1 x getLastMessageDate 1 x addLabel 1 x moveToArchive 1 x removeLabel

每个线程 5 次调用。

所以,我想,我每天要打 10 个电话/5 分钟,或者 2880 个电话,只是为了寻找消息。然后,假设我在一天中发现 1,000 条消息,另外还有 5,000 个电话。加起来就是 7,880 个电话,这在我认为的配额限制之下,但我有点不清楚。根据配额限制下的https://docs.google.com/a/macros/latinschool.org/dashboard,对于像我这样的 Google Apps for Edu 帐户,我应该能够读取 10,000 个 GMail 和每天 10,000 个 GMail 写操作。我认为我所有的电话都属于这两者之一。

我可以减少我正在使用的标签/次数的数量,而不是获取主题(我正在使用它进行调试),但除此之外,我不确定如何使这个脚本更有效率。而且我完全不清楚我是如何达到配额的(见上面的数学)。

这是我的代码:

/**
 * Expire mail after set time by archiving based on labels
 * based on http://googleappsdeveloper.blogspot.com/2011/07/gmail-snooze-with-apps-script.html
 * For more information on interacting with GMail labels, see
 * https://developers.google.com/apps-script/class_gmaillabel
 */

var expiretimes = [5,15,30,60,120,180,240,480,720];  // times in minutes to expire messages


function getLabelName(i) {
  return "expire/expire " + i;
}

function setup() {
  // Create the labels we’ll need for expiring
  GmailApp.createLabel("expire");
  for (var expt = 0; expt < expiretimes.length; expt++) {
    GmailApp.createLabel(getLabelName(expt));
  }
    GmailApp.createLabel("expired");
}


function expiremsgs(expiremin) {
  // get current date
  var nowdate = new Date();
  Logger.log(nowdate);

  // get the label for given name
  var label = GmailApp.getUserLabelByName(getLabelName(expiremin));
  var expiredlabel = GmailApp.getUserLabelByName("expired");
  var threads = label.getThreads();
  Utilities.sleep(1000);
  for (var i = 0; i < threads.length; i++) {
    Logger.log("i: " + i);
    Logger.log(threads[i].getFirstMessageSubject());
    var lastmsgdate = threads[i].getLastMessageDate();
    Logger.log(lastmsgdate);
    var minold = (nowdate-lastmsgdate)/60000; // convert from ms to minutes
    Logger.log(minold);
    if (minold > expiremin) {
      threads[i].addLabel(expiredlabel);
      threads[i].moveToArchive();
      threads[i].removeLabel(label);
      Logger.log("Archived");
    }
  Utilities.sleep(1500);
  }
};

function expire() {
  for (var expt = 0; expt < expiretimes.length; expt++) {
    expiremsgs(expt);
  }
}
4

1 回答 1

1

我仔细看了看你在做什么,看起来你的数学是正确的。但是,我知道在使用电子表格时使用批处理操作是最佳实践。所以,我看了一些参考资料,发现了一些关键功能:

GmailApp.moveThreadsToArchive(GmailThreads[]);
label.removeFromThreads(GmailThreads[]);
label.addToThreads(GmailThreads[]);

我假设这些函数将减少您使用 API 进行的读/写调用的数量。(如果我错了,请谷歌 OP 纠正我。)

尽管如此,当我在玩你的代码时,我发现这些函数一次只能处理 100 个线程,所以如果超过了,那么操作必须批处理。我还检查了调用 GmailApp 服务的速度和可扩展性,发现大多数调用的延迟与所涉及的项目数量大致无关。至少在我的测试中,批量归档 6 个线程大约需要(在一两秒内)与 100 个相同的时间。在出Gmail之前,我也尽力在脚本中做尽可能多的事情。最后,我修改了您与超时交互的方式。我一生都无法弄清楚你是如何获得数组中的值的,所以我修改了它以及标签。他们现在将阅读“过期/在 15 分钟内”等。

另一种方法可能是运行一次搜索,一次性查找所有标签,然后检查标签。但是,当您检查每个线程的属性时,这可能仍会向 Gmail 调用过多的调用。

有了所有这些,这是我对您的代码的迭代:

var expiretimes = [5,15,30,60,120,180,240,480,720];

function getLabelName(i) {
  return "expire/in " + expiretimes[i]  + " min";
}

function setup() {
  GmailApp.createLabel("expired");
  GmailApp.createLabel("expire");
  for (var expt = 0; expt < expiretimes.length; expt++) {
    GmailApp.createLabel(getLabelName(expt));
  }
}

function expire() {
  var allExpThreads = [];
  for (var expt = 0; expt < expiretimes.length; expt++) allExpThreads = allExpThreads.concat(expiremsgs(expt));
  if(allExpThreads.length > 100) batchExpire(allExpThreads);
  else GmailApp.moveThreadsToArchive(allExpThreads).getUserLabelByName("expired").addToThreads(allExpThreads);
}

function expiremsgs(expiremin) {
  var label = GmailApp.getUserLabelByName(getLabelName(expiremin));   
  var threads = label.getThreads();
  if(threads.length > 0){   
    var threadsToExpire = threads.filter(msgExpired, {date: new Date(), min: expiretimes[expiremin]});
    if(threadsToExpire.length > 100) batchRemoveLabel(threadsToExpire,label);
    else if(threadsToExpire.length > 0) label.removeFromThreads(threadsToExpire);
    return threadsToExpire;
  }
  return [];
}

function msgExpired(thread) {
  return this.date - thread.getLastMessageDate() / 6000 > this.min;
}

function batchRemoveLabel(threads,label) {
  var start = 0, end = 100;
  do {
    label.removeFromThreads(threads.slice(start,end));
    start = end;
    end = end > threads.length - 100 ? threads.length : end + 100;
  } while (start < threads.length);
}

function batchExpire(threads) {
  var start = 0, end = 100;
  var expLabel = GmailApp.getUserLabelByName("expired");
  do {
    GmailApp.moveThreadsToArchive(threads.slice(start,end));
    expLabel.addToThreads(threads.slice(start,end));
    start = end;
    end = end > threads.length - 100 ? threads.length : end + 100;
  } while (start < threads.length);
}
于 2012-12-21T04:53:02.497 回答