0
votes

I'm trying to find out if it is possible to set something up to forward emails to alternating recipients.

When I receive emails, a GMail filter tags some of them, with "elephant", for example.

There are multiple people who can handle "elephant" emails, so I want to forward each new email to one of them, cycling through the list of "elephant handlers". (Joe, Amy, and Tammy, say.) Their email addresses are available in a spreadsheet.

         A
1 [email protected]
2 [email protected]
3 [email protected]

Pseudo code:

Get first unread email
  Forward email to Joe
Get next unread email
  Forward email to Amy
Get next unread email
  Forward email to Tammy
Go to start

How can I accomplish this in Google Apps Script, so that it handles all new emails as they arrive?

1

1 Answers

1
votes

It's possible to do this in a number of ways. In the world of telephony, the behavior is called a Hunt Group. Here's one suggestion that borrows that concept to get you started.

Assumptions:

  • You're using Gmail.
  • The script will belong to the same account holder as the Gmail account.

Approach:

  • You will set up a filter in Gmail to identify incoming messages that meet your criteria - the "elephant" emails.

  • In this filter, you will apply a label - "elephant" - to new emails that will be used by the script to identify "work to do".

  • A spreadsheet will be used to contain a script that will scan for unread messages related to the "elephant" Label and forward them.

  • The script will be set to Trigger on a timer event at an interval that suits you.

  • The spreadsheet will contain a list of (properly formatted) destination email addresses; Joe, Amy, Tammy. The script will read these and use them in order.

  • Once an email is processed, it will be marked as "read". You could optionally un-label, relabel, archive, or trash them.

The Script

This script keeps track of which recipient will get the next forwarded message by using ScriptProperties. If you expect very large numbers of messages, you'll need to enhance it to support getting messages in batches.

Remember to change labelName appropriately.

The script does some error checking, but doesn't validate email addresses - it's possible that messages may end up failing the forwarding operation because of that. Caveat Emptor.

This is also available as a gist.

/**
 * Retrieves a given user label by name and forwards unread messages
 * associated with that that label to a member of the Hunt Group.
 */
function huntGroupForward() {
  // get the label for given name
  var labelName = "elephant"
  var label = GmailApp.getUserLabelByName(labelName);
  if (label == null) throw new Error("No messages for label "+labelName);
  // get count of all threads in the given label
  var threadCount = label.getUnreadCount();
  if (threadCount == 0) return;  // quick exit if nothing to do.
  var threads = label.getThreads();
  var messages = [];
  for (var i in threads) {
    if (threads[i].isUnread()) {
      messages = messages.concat( threads[i].getMessages() );
    }
  }
  for (var i = 0; i < messages.length; i++) {
    if (messages[i].isUnread()) {
      messages[i].forward(nextHuntGroupMember());
      messages[i].markRead();
    }
  }
};

/*
 * Global object to store working copy of the Hunt Group
 */
var huntGroup = { next : 0, members : [] };

/*
 * Get the email address of the next Hunt Group Member
 * to forward a message to.
 */
function nextHuntGroupMember() {
  if (huntGroup.members.length == 0) {
    // Load members
    var sheet = SpreadsheetApp.getActiveSheet();
    var data = sheet.getDataRange().getValues();
    for (var i = 0; i < data.length; i++) {
      huntGroup.members.push(data[i][0])
    }
    // Make sure we have members
    if (huntGroup.members.length == 0) {
      throw new Error("Found no email addresses");
    }
  }

  // Retrieve next index. Properties are always stored as strings, so
  // we need to parse the retrieved value to use it as a Number.
  var next = parseInt(ScriptProperties.getProperty("nextHuntGroupMember"));
  if (next != null) {
    huntGroup.next = next;
  }
  else {
    next = 0;
  }

  // get next member to be used
  var nextMember = huntGroup.members[next];
  // ... then move on to new next (increment modulo list length)
  next = ++next % huntGroup.members.length;
  // store the new next value
  ScriptProperties.setProperty("nextHuntGroupMember", next);

  return nextMember;  
}

Trigger

Once you're happy with the script, set it up to run periodically. This is how you'd set it to run every hour:

Trigger