【问题标题】:GMail API: Script works when run manually, but not when triggeredGMail API:脚本在手动运行时有效,但在触发时无效
【发布时间】:2018-07-15 04:05:58
【问题描述】:

Gmail API (script.google.com) 的以下脚本在我手动运行时没有任何问题,但当它由 Google 使用基于时间的触发器触发时,它会失败。

function noSend(e) {  
  var drafts = GmailApp.getDrafts();
  var callback = function(draft) {
    function isMyEx(draft) {
      var recipient = draft.getMessage().getTo();
      var isTheirEmail = /nameofmyex/.test(recipient);
      return isTheirEmail; };
    if(isMyEx(draft)) {
      draft.update('', '', ''); 
      draft.deleteDraft(); 
    } else {  } };

  drafts.forEach(callback); return;
};

问题:如果手动运行脚本没有出现错误,我该如何调试?

即添加 Logger.log() 并没有帮助,因为我看到它的输出的唯一方法是手动运行脚本 - 但是当我手动运行脚本时脚本可以正常工作。

据我从谷歌的网站(我不明白布局)可以看出,有问题的错误是:

TypeError: Function getMessage in Object [object Object] was not found

这对我来说没有任何意义,因为唯一一次调用 getMessage 方法是由函数 draft 中的 isMyEx,它不应该将 Object 作为其原型,而是应该有 GmailDraft 作为它的原型,它肯定有一个 getMessage 方法。

到目前为止,我唯一的猜测是它与function hoisting 有关,我不太了解其规则。但是我已经尝试了几种排序函数的方法以及在哪里定义它们——当我手动运行脚本时,所有这些方法都有效。同样,当脚本由 Google 自动触发时才会发生此故障,这让我感到困惑不已。

相关问题:Gmail API message.list from trigger
Function works only when launched manually (not when triggered) in Google Apps Script Form

【问题讨论】:

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


    【解决方案1】:

    这是非常愚蠢的,但以防将来可能对其他人有所帮助(它不会,因为这种愚蠢程度可能无法复制,但是):

    在我的脚本的原始版本中,函数isMyExdoSend 之外的全局范围内声明,或多或少类似于以下内容:

    function isMyEx(draft) {
          var recipient = draft.getMessage().getTo();
          var isTheirEmail = /nameofmyex/.test(recipient);
          return isTheirEmail; };
    
    function noSend(e) {  
      var drafts = GmailApp.getDrafts();
      var callback = function(draft) {
        if(isMyEx(draft)) {
          draft.update('', '', ''); 
          draft.deleteDraft(); 
        } else {  } };
    
      drafts.forEach(callback); return;
    };
    

    由于isMyEx是在noSend之前定义的,所以当我点击按钮为脚本设置触发器时,要触发的默认函数是首先定义的函数isMyEx。如果在doSend 之外调用它,而不是作为内部回调,当然会抛出我描述的错误。

    *这可能被认为是不好的做法。如果是这样,请理解我这样做是出于无知,而不是出于向本网站访问者传播不良编码实践的恶意意图。特别是,请不要对我大喊大叫。我已经为这种糟糕的编码习惯受到了惩罚,因为它已经回来咬我,见下文。

    故事的寓意:触发器并非针对整个脚本。为脚本中的每个函数单独设置一个触发器不仅是可能的,而且实际上是必要的。因此,如果您不费心查看脚本中为哪个函数设置触发器,请不要像我一样在您没有得到想要的结果时感到惊讶。

    我之所以知道这一点,是因为在将isMyEx 的定义放入noSend(然后放入callback)之后,当我再次单击脚本的触发按钮时,下面出现了一条红色消息触发器Selected function not found。起初这对我来说没有意义,因为我认为触发器是针对整个脚本的,但后来我更仔细地查看按钮并意识到这意味着触发器只是试图运行函数isMyEx,不是整个脚本文件(我想这对更大的脚本有意义)。无论如何,在将isMyEx 从全局范围移出后,无法再找到该函数是有道理的。

    无论如何,在我将触发器更改为 noSend 而不是 isMyEx 后,自动触发器一切正常/完美,而不仅仅是在我手动运行脚本时。

    【讨论】:

      猜你喜欢
      • 2011-12-08
      • 1970-01-01
      • 2021-03-12
      • 1970-01-01
      • 2022-01-03
      • 2021-06-12
      • 1970-01-01
      • 2019-07-10
      • 2017-12-07
      相关资源
      最近更新 更多