从Gmail线程中收集唯一的电子邮件地址

Collect unique email addresses from Gmail threads

本文关键字:唯一 电子邮件地址 Gmail 线程      更新时间:2023-09-26

我是Google Apps Script的新手,我正在尝试为电子表格制作一个脚本,在该脚本中,我将在工作表中存储通过.getFrom()方法找到的所有电子邮件地址,并忽略相同的电子邮件地址,这样我就只能获得一个电子邮件地址,而不是多次。到目前为止,存储工作是成功的,但忽略相同的电子邮件是不起作用的。我在表格栏中多次收到相同的电子邮件。

这是我的代码:

      var n=threads.length;
      var messages=thread.getMessages();
      var getfrom = 0;
      var allMails = [];
      for (var i=0; i<n; i++)
      {
         for (var j=0; j<messages.length; j++)
         {
            var message=messages[j];
            getfrom = message.getFrom();
            var first_name = getfrom.substring(0, getfrom.indexOf(" "));
            var last_name = getfrom.substring(getfrom.indexOf(" ")+1, getfrom.indexOf(" <"));
            var email_address = 0;
            if (first_name == '' && last_name == '')
            {
               email_address = getfrom;
            } else {
               email_address = getfrom.substring(getfrom.indexOf("<")+1, getfrom.indexOf(">"));
            }
            // This is how I check if I already have the email address or not
            if (email_address == my_email || email_address[j] == email_address[j-1])
            {
               continue;
            }
          }
          allMails.push([email_address]);
      }
      Logger.log(allMails);
      sheet1.getRange(2, 3, n, 1).setValues(allMails);
      Browser.msgBox("Operation complete");

如何忽略重复的值并获取一个电子邮件地址而不是多次?

您可以在向列表中添加电子邮件之前确保唯一性,也可以先构建完整列表,然后再删除重复列表。

选项1:预过滤器

这个例子构建了一个一维的地址数组;因为它是一个简单的数组,我们可以使用JavaScript内置的.indexOf()方法来检查其唯一性。在检查完所有线程之后,使用另一个内置的array map(),将简单数组转换为二维数组以存储在电子表格中。不过在此之前,数组会进行排序,因为我们可以。您可能需要进行其他筛选,例如删除"无回复"地址。

function getUniqueFromAddresses1() {
  var my_email = Session.getActiveUser().getEmail();
  var threads = GmailApp.getInboxThreads();
  var n=threads.length;
  var allMails = [];
  for (var i=0; i<n; i++)
  {
    var thread = threads[i];
    var messages=thread.getMessages();
    for (var j=0; j<messages.length; j++)
    {
      var message=messages[j];
      var getfrom = message.getFrom();
      // Use RegEx to extract just email address
      var email_address = getfrom.match(/[^<> ]*'@[^> ]*/)[0];
      // Skip messages I sent or addresses already collected
      var index = allMails.indexOf(email_address);
      if (email_address !== my_email && allMails.indexOf(email_address) == -1) {
        allMails.push(email_address);
      }
    }
  }
  // Could do further filtering & sorting of allEmails here
  allMails = allMails.sort()
  Logger.log(JSON.stringify(allMails));
  // convert allMails array to two-dimensional array
  allMails = allMails.map( function(item){
    return [item];
  });
  Logger.log(JSON.stringify(allMails));
  // Store in spreadsheet; use dimensions of array to avoid mismatching range size
  sheet1.getRange(2, 3, allMails.length, allMails[0].length).setValues(allMails);
  debugger;  // Pause in debugger
  Browser.msgBox("Operation complete");
}

选项2:后置过滤器

这是另一种方法,在构建数组后删除重复项。JavaScript的神奇之处就在于这个答案。我们仍然使用一维数组来收集和筛选地址。还有一个额外的步骤需要从列表中删除我们自己的地址。

性能:这应该比方法1更快,因为需要更少的比较。然而,整个操作中使用的大部分时间都与访问消息有关,因此本地JavaScript中节省的时间可以忽略不计。

function getUniqueFromAddresses2() {
  var my_email = Session.getActiveUser().getEmail();
  var threads = GmailApp.getInboxThreads();
  var n=threads.length;
  var allMails = [];
  for (var i=0; i<n; i++)
  {
    var thread = threads[i];
    var messages=thread.getMessages();
    for (var j=0; j<messages.length; j++)
    {
      var message=messages[j];
      var getfrom = message.getFrom();
      // Use RegEx to extract just email address
      var email_address = getfrom.match(/[^<> ]*'@[^> ]*/)[0];
      // Save the address      
      allMails.push(email_address);
      // Skip messages I sent or addresses already collected
      var index = allMails.indexOf(email_address);
      if (email_address !== my_email && allMails.indexOf(email_address) == -1) {
        allMails.push(email_address);
      }
    }
  }
  // Remove duplicates - https://stackoverflow.com/a/32533637/1677912
  allMails = allMails.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, []);
  // Remove my address
  if ((mine=allMails.indexOf(my_email)) > -1) allMails.splice(mine,1);
  // Could do further filtering & sorting of allEmails here
  allMails = allMails.sort()
  Logger.log(JSON.stringify(allMails));
  // convert allMails array to two-dimensional array
  allMails = allMails.map( function(item){ return [item]; });
  Logger.log(JSON.stringify(allMails));
  sheet1.getRange(2, 3, n, 1).setValues(allMails);
  debugger;  // Pause in debugger
  Browser.msgBox("Operation complete");
}

你是怎么得到这些电子邮件地址的

最初的函数需要几个步骤来识别message.getFrom()返回的字符串中的电子邮件地址。这很棘手,因为这个字符串可以只包含一个电子邮件地址,或者一个名字和一个地址。通过使用正则表达式只匹配电子邮件地址,并忽略字符串中的任何其他文本,可以简化操作。

      // Use RegEx to extract just email address
      var email_address = getfrom.match(/[^<> ]*'@[^> ]*/)[0];

表达式查找@及其前后的文本,这些文本以空格或大括号为边界。你可以在一个在线演示中尝试一下。

/[^<> ]*'@[^> ]*/
  [^<> ]* match a single character not present in the list below
    Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
   <>  a single character in the list "<> " literally (case sensitive)
  '@ matches the character @ literally

您需要交叉检查您的allMails数组中是否有给定的电子邮件地址,以确保它不在列表中,但您无法直接检查allMails,因为它是一个二维数组。

我添加一个一维数组纯粹是为了交叉检查。

  var n=threads.length;
  var messages=thread.getMessages();
  var getfrom = 0;
  var allMails = [];
  var cross_check = [];
  for (var i=0; i<n; i++)
  {
     for (var j=0; j<messages.length; j++)
     {
        var message=messages[j];
        getfrom = message.getFrom();
        var first_name = getfrom.substring(0, getfrom.indexOf(" "));
        var last_name = getfrom.substring(getfrom.indexOf(" ")+1, getfrom.indexOf(" <"));
        var email_address = 0;
        if (first_name == '' && last_name == '')
        {
           email_address = getfrom;
        } else {
           email_address = getfrom.substring(getfrom.indexOf("<")+1, getfrom.indexOf(">"));
        }
        if(email_address != my_email && cross_check.indexOf(email_address) == -1){
           cross_check.push(email_address);
           allMails.push([email_address]);
        } 
      }
  }
  Logger.log(allMails);
  sheet1.getRange(2, 3, n, 1).setValues(allMails);
  Browser.msgBox("Operation complete");

请参阅indexOf函数的文档,它解释了我们为什么检查-1,在这里:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

同时检查Gmail提取器-它将Gmail中的电子邮件地址保存在谷歌电子表格中。