Google Apps脚本类GmailApp批处理操作?

时间:2012-08-19 18:45:27

标签: google-apps-script google-sheets gmail

我一直在玩GAS一个月左右,我已经相当熟悉使用批处理操作来读/写电子表格(例如getValues(),setValues())。但是,我目前正在编写一个脚本,使用GmailApp类从Gmail中提取大量数据,我的代码运行速度非常慢(甚至超时),我似乎无法弄清楚如何使用批处理操作我正在努力做什么。这是我到目前为止的代码(电子邮件地址和名称已更改):

 function fetchEmails(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var threads = GmailApp.search('in: label:searchedLabel');
  var messages = new Array();

  function Email(message){
  this.date = new Date(message.getDate());
  this.body = message.getBody();
  }

  for(var i=0;i<threads.length;i++){
    for(var j=0;j<threads[i].getMessageCount();j++){
      if(threads[i].getMessages()[j].getFrom()=="firstName lastName <email@domain.com>"){
       var message = new Email(threads[i].getMessages()[j]);
       messages.push(message);
      }
    }
  }  
}

正如您所看到的,我正在查询具有给定标签的所有线程的电子邮件, 为自定义电子邮件对象(将电子邮件的正文和日期作为属性)创建对象构造函数。然后我循环遍历每个线程,当给定的电子邮件与我正在寻找的发件人匹配时,我为该电子邮件创建了一个Email对象的实例,并将该Email对象放入一个数组中。目标是最终我将拥有一系列电子邮件对象,这些对象都来自我想要的发件人。但是,您可能已经注意到代码过于频繁地调用Google的API,但我似乎无法找到与Gmail连接的批处理操作。有任何想法吗?非常感谢。

1 个答案:

答案 0 :(得分:12)

我认为您正在寻找GmailApp.getMessagesForThreads()。

function fetchEmails(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var threads = GmailApp.search('label:searchedLabel');
  var messages = new Array();

  function Email(message){
    this.date = new Date(message.getDate());
    this.body = message.getBody();
  }

  var gmailMessages = GmailApp.getMessagesForThreads(threads);

  for(var i=0;i<thread.length;i++){
    var messagesForThread = gmailMessages[i];
    for(var j=0;j<messagesForThread.length;j++){
      if(messagesForThread[j].getFrom()=="firstName lastName <email@domain.com>"){
       var message = new Email(messagesForThread[j]);
       messages.push(message);
      }
    }
  }  
}

当然你也可以更简洁地写一下(对不起,我无法找到教育JavaScript奇迹的机会):

function fetchEmails(){
  var messages = Array.prototype.concat.apply([], GmailApp.getMessagesForThreads(
      GmailApp.search('label:searchedLabel')).map(function(messagesForThread) {
    return messagesForThread.filter(function(message) {
      return message.getFrom() == "firstName lastName <email@domain.com>";
    }).map(function(message) {
      return { date: new Date(message.getDate()), body: message.getBody() };
    });}));
}

这使得总共可以拨打两次Gmail电话,因此速度很快。

事实上,如果你按照上面的建议将'from'部分整合到搜索中,你只需要:

function fetchEmails(){
  var messages = Array.prototype.concat.apply([], GmailApp.getMessagesForThreads(
    GmailApp.search('label:searchedLabel from:email@domain.com')).map(
      function(messagesForThread) {
        return messagesForThread.map(function(message) {
          return { date: new Date(message.getDate()), body: message.getBody() };
      });}));
}

最后,既然你实际上并不关心线程结构,你可以在地图之前连接数组,这导致了这个:

function fetchEmails(){
  var messages = GmailApp.getMessagesForThreads(
        GmailApp.search('label:searchedLabel from:email@domain.com'))
      .reduce(function(a, b){ return a.concat(b); })
      .map(function(message) {
         return { date: new Date(message.getDate()), body: message.getBody() }; 
      });
}

(如果您关心线程结构,我会留在早期的示例中,您只是给出了一个最小的例子)。