Gmail 加载项 Google 脚本错误行为

Gmail Add On Google Script incorrect behaviour

我正在创建一个 Gmail 插件,它将电子邮件的某些信息发送到后端端点,为了做到这一点,它必须 select 并按以下方式格式化电子邮件的电子邮件地址:

  1. 如果电子邮件在收件箱中,地址应该是发件人之一。
  2. 如果邮件处于已发送状态,地址应为收件人地址。
  3. 如果GmailMessage.getFrom()GmailMessage.getTo()的结果是电子邮件格式的字符串,那就是地址,不需要执行格式。
  4. 如果GmailMessage.getFrom()GmailMessage.getTo()的结果是一个格式为John Doe <john@doe.com>的字符串,那么地址应该是尖括号之间的子字符串。

所以我为此编写了以下代码

for (var i = 0; i < messages.length; i++) {

    var address = '';
    var name = '';
    var from = messages[i].getFrom()
    var to = messages[i].getTo();
    Logger.log(from);
    Logger.log(to);

    if (messages[i].isInInbox()) {
      Logger.log('inbox'); // (*)
      if (/<(.*?)>/g.test(from)) {
        Logger.log(/<(.*?)>/g.test(from));
        Logger.log('true');
        address = /<(.*?)>/.exec(from)[1];
      } else {
        Logger.log(/<(.*?)>/g.test(from)); // (**)
        Logger.log('false');
        address = /^(([^<>()\[\]\.,;:\s@"]+(\.[^<>()\[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/g.exec(from)[0];
      }
      name = /^(.*?)@/.exec(address);
    } else {
      Logger.log('sent');
      if (/<(.*?)>/g.test(to)) {
        Logger.log(/<(.*?)>/g.test(to));
        Logger.log('true');
        address = /<(.*?)>/.exec(to)[1];
      } else {
        Logger.log(/<(.*?)>/g.test(to));
        Logger.log('false');
        address = /^(([^<>()\[\]\.,;:\s@"]+(\.[^<>()\[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/g.exec(to)[0];
      }
      name = /^(.*?)@/.exec(address);
    }
  }

其中 messages 是一组 GmailMessage 对象。 问题是,在其中一条收件箱消息中,'from' 地址对 /<(.*?)>/g 正则表达式的计算结果为真,但仍然进入了 else 语句。 更明确地说,Logger 的输出如下:

[19-10-14 13:52:14:750 PDT] "Foo Bar" <foo@bar.com>
[19-10-14 13:52:14:750 PDT] john@doe.com <---- selected address
[19-10-14 13:52:14:751 PDT] sent 
[19-10-14 13:52:14:751 PDT] false <---- it's a "simple string", not enclosed by <>
[19-10-14 13:52:14:752 PDT] false

[19-10-14 13:52:14:753 PDT] John Doe <john@doe.com> <---- selected address
[19-10-14 13:52:14:754 PDT] "Foo Bar" <foo@bar.com>
[19-10-14 13:52:14:755 PDT] inbox
[19-10-14 13:52:14:755 PDT] true <---- enclosed by <>
[19-10-14 13:52:14:755 PDT] true

[19-10-14 13:52:14:757 PDT] "Foo Bar" <foo@bar.com>
[19-10-14 13:52:14:757 PDT] John Doe <john@doe.com> <---- selected address
[19-10-14 13:52:14:757 PDT] sent
[19-10-14 13:52:14:758 PDT] true <---- enclosed by <>
[19-10-14 13:52:14:758 PDT] true

[19-10-14 13:52:14:760 PDT] John Doe <john@doe.com> <---- selected address
[19-10-14 13:52:14:760 PDT] "Foo Bar" <foo@bar.com>
[19-10-14 13:52:14:761 PDT] inbox
[19-10-14 13:52:14:761 PDT] true <---- enclosed by <>
[19-10-14 13:52:14:761 PDT] false <---- it's entering to the else statement nonetheless

关于为什么会发生这种奇怪行为的任何线索?我真的很努力地想弄清楚这段代码有什么问题,但我真的不知道它会是什么。

编辑:我进行了更多测试,奇怪的是,如果我将表达式 /<(.*?)>/g.exec(from) 放在 Logger.log('inbox') 下方,表达式 /<(.*?)>/g.exec(from) 等于 null( *) 并等于 else 语句 (**) 中的 [<john@doe.com>, john@doe.com]。谁能解释这种行为?

导致问题的是全局修饰符。带有全局修饰符的正则表达式在调用之间是有状态的,包括对 test() 的调用。状态的维护使得 exec() 之类的东西可以迭代地调用到 return 下一场比赛。由于您对表达式使用文字,因此解释器只是将其优化为表达式的一个实例。相同实例 + 有状态 + 使用相同 arg 多次调用 test() == 你所看到的。

去掉那些表达式中的g标志就可以了。它甚至不需要您使用它的方式,因为您正在测试 any 匹配。