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

Collect unique email addresses from Gmail threads

我是 Google Apps 脚本的新手,我正在尝试为传播sheet 制作一个脚本,我将在其中存储 .getFrom() 找到的所有电子邮件地址sheet 中的方法并忽略相同的电子邮件地址,以便我只获得一个电子邮件地址,而不是多次。到目前为止,存储工作成功,但忽略相同的电子邮件不起作用。我在 sheet 的专栏中多次收到相同的电子邮件。

这是我的代码:

      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");

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

您需要交叉检查给定电子邮件地址的 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

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

选项 1:预过滤

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

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:Post-过滤器

这是替代方法,在构建数组后删除重复项。这里的 JavaScript 魔法是从 this answer 中提取的。我们仍然使用一维数组来收集和过滤地址。从列表中删除我们自己的地址还需要一个额外的步骤。

性能: 这应该比方法 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 - 
  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];

该表达式查找 @ 及其前后的文本,由 space 或尖括号包围。您可以在 online demo.

中尝试一下
/[^<> ]*\@[^> ]*/
  [^<> ]* 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

同时检查 Gmail Extractor - 它会将来自 Gmail 的电子邮件地址保存在 Google 电子表格中。