1

I found a similar question here: Get e-mail addresses from Gmail messages received but the difference is that I want "To:" addresses, not "From:".

I have a catch-all email address at my domain. Except I'm getting a ton of spam mail in there, so my host is telling me I need to setup individual email accounts for all the ones I've used. I have 100s of unique emails at my domain name that I've used, but no easy way to put them all in a list.

I'm trying to figure out how to do this with GmailApp API. I tried the below code, but it didn't quite get me what I was looking for. I'd like to get all unique/distinct email addresses in my Gmail account to which I've received emails like *@mydomain.com.

function getEmails() { 
  // http://stackoverflow.com/a/12029701/1536038  
  // get all messages      
  var eMails = GmailApp.getMessagesForThreads(
    GmailApp.search('after:2015/1/14 before:2016/3/12'))
      .reduce(function(a, b) {return a.concat(b);})
      .map(function(eMails) {
    return eMails.getTo() 
  });

  // sort and filter for unique entries  
  var aEmails = eMails.sort().filter(function(el,j,a)
    {if(j==a.indexOf(el))return 1;return 0});  

  // create 2D-array
  var aUnique = new Array();  
  for(var k in aEmails) {
    aUnique.push([aEmails[k]]);
  }

  // add data to sheet
  SpreadsheetApp.getActiveSheet().getRange(1, 1, aUnique.length, 1)
    .setValues(aUnique);
} 

////////////////// After getting the answer below, I've modified this code with paging. But it can still be improved by somehow incorporating the paging into the loop and being able to get all unique emails in one pass.

function GetAddresses ()
{
  // Get the active spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();  

  // Create / empty the target sheet
  var sheetName = "Pixeltrics Emails";
  var sheet = ss.getSheetByName (sheetName) || ss.insertSheet (sheetName, ss.getSheets().length);
  sheet.clear();

  // Get all messages in a nested array (threads -> messages)
  var addressesOnly = [];
  var messageData = [];

  var pageSize = 500;
  var startIndex = 500;
   // Get all messages for the current batch of threads
     var eMails = GmailApp.getMessagesForThreads(
       GmailApp.search('to:(@mydomain.com)',startIndex,pageSize))
       .reduce(function(a, b) {return a.concat(b);})
      .map(function(eMails) {
        var matched = eMails.getTo().match(/<[^@]*@mydoman\.com>/ig);
        return (matched ? matched : []);
      })
     .reduce(function(a, b) {return a.concat(b);});

 // lowercase, filter for unique entries, sort
  var aEmails = eMails.map(function(text) {return text.toLowerCase().slice(1, -1);})
                      .filter(function(el,j,a) {return j == a.indexOf(el)})
                      .sort();

  // create 2D-array
  aUnique = aEmails.map(function(el) {return [el];}); 

   // add data to sheet
  SpreadsheetApp.getActiveSheet().getRange(1, 1, aUnique.length, 1)
    .setValues(aUnique);
}

1 Answer 1

2

The method getTo returns a string with names of recipients along with email addresses. You need to extract the addresses from it, specifically those matching *@mydomain.com. This is done with a regular expression below:

var matched = eMails.getTo().match(/<[^@]*@mydomain\.com>/ig);

The result is an array or null; I replace null by empty array and then flatten the results again (reduce by concat).

Additionally, all addresses are made lowercase to correctly locate duplicates. The command slice(1,-1) gets rid of angle brackers around email. Then uniques are filtered and the result is sorted. (I think it's better to sort after filtering out duplicates: a much smaller array to sort.)

And since we're all about .map and .reduce in this function, I also used .map when creating a 2D array.

function getEmails() { 
  // modified from http://stackoverflow.com/a/12029701  
  // get all messages, extract matching addresses from To fields 
  var eMails = GmailApp.getMessagesForThreads(GmailApp.search('after:2015/1/14 before:2016/3/12'))
      .reduce(function(a, b) {return a.concat(b);})
      .map(function(eMails) {
        var matched = eMails.getTo().match(/<[^@]*@mydomain\.com>/ig);
        return (matched ? matched : []);
      })
      .reduce(function(a, b) {return a.concat(b);});

  // lowercase, filter for unique entries, sort
  var aEmails = eMails.map(function(text) {return text.toLowerCase().slice(1, -1);})
                      .filter(function(el,j,a) {return j == a.indexOf(el)})
                      .sort();

  // create 2D-array
  aUnique = aEmails.map(function(el) {return [el];}); 

  // add data to sheet
  SpreadsheetApp.getActiveSheet().getRange(1, 1, aUnique.length, 1)
    .setValues(aUnique);
} 
2
  • Thank you, the only thing think it can still benefit from is adding a startIndex and pageSize since I think the API only allows a max of 500 to come back. Now if it could keep searching in chunks of 500, and then give back all the actual unique emails that would be absolutely perfect. I think I know how to add paging based on other examples, but afraid it might time out if it keeps searching too long to do it all at once.
    – pixelwiz
    Mar 14, 2016 at 1:07
  • Added paging...
    – pixelwiz
    Mar 14, 2016 at 1:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.