11
votes

I'm trying to implement a simple google script that processes each message that is received by a Gmail user.

I've found an example that does something like this:

var threads = GmailApp.getInboxThreads();
for (var i=0; i < threads.length; i++) {
   var messages = threads[i].getMessages();

   for (var j=0; j < messages.length; j++) {
       if (!messages[j].isUnread()) {
         continue; 
       }
      //process message
   }
}

That is: I iterate through all messages in the inbox and search for the unread ones. This is very slow on just 1800 messages.

Ideally, I'm looking for a trigger that gets fired once each new message is received.

If there is no such thing, I would try to make use of this that I saw:

GmailApp.getMessageById(id)
6

6 Answers

15
votes

Sorry for the late response but I just had the same type of problem and I ended up using GmailApp.search() ... hope this helps.

// find unread messages
var threads = GmailApp.search('is:unread');
....

WARNING

This call will fail when the size of all threads is too large for the system to handle. Where the thread size is unknown, and potentially very large, please use the 'paged' call, and specify ranges of the threads to retrieve in each call.

Take a look at GmailApp.search(query) and GmailApp.search(query, start, max)

9
votes

Unfortunately there in no trigger that fires for each recieved message. There is however a good workaround:

Set up a filter rule that assigns a special label, "ToBeProcessedByScript" as example, to all incoming messages. Since wildcards don't really work in Gmail filters use the to: field.

Run a time-triggered script that collects all new message threads with GmailApp.getUserLabelByName("ToBeProcessedByScript").getThreads(). Remove the special label just before processing the new messages.

4
votes

you can use

GmailApp.getInboxThreads(0, 50);

to initialize the variable with first fifty mail.

2
votes

You can create a time trigger as djtek mentioned but instead of labeling all messages and then retrieve labeled messages, you can just get the number of the unread messages, and retrieve threads from 0 to the number of the unread messages, following a code that works for me:

 function getUnreadMails() {
   var ureadMsgsCount = GmailApp.getInboxUnreadCount()
   if(ureadMsgsCount>0)
   {        
     var threads = GmailApp.getInboxThreads(0, ureadMsgsCount);
     for(var i=0; i<threads.length; i++)
     {
       if(threads[i].isInInbox())
       {
          var messages = threads[i].getMessages();
          for(var j=0; j<messages.length; j++)
          {
             Logger.log(messages[j].getSubject());
             // process unread message
          }
       }
     }
   }
 }
2
votes

I have extended the code with checking if the first message is really the one which is unread. If it is not it will check the next message and will continue untill it finds the unread message:

function getUnreadMails() {
   var ureadMsgsCount = GmailApp.getInboxUnreadCount();
   var threads;
   var messages;
   var k=1;
   if(ureadMsgsCount>0)
   {        
     threads = GmailApp.getInboxThreads(0, ureadMsgsCount);
     for(var i=0; i<threads.length; i++)
     {
       if(threads[i].isInInbox())
       {
          messages = threads[i].getMessages();
          for(var j=0; j<messages.length; j++)
          {

             while (messages[j].isUnread() === false)
             {
             threads=GmailApp.getInboxThreads(k, ureadMsgsCount);
             messages = threads[i].getMessages();
             k++;
             }
             Logger.log(messages[j].getSubject());

             // process unread message
          }
       }
     }
   }
 }
1
votes
function getUnreadMessages(threadLimit) {
  function flatten(arr) { return [].concat.apply([], arr) }
  var threadsWithUnreadMessages = GmailApp.search('is:unread', 0, threadLimit)
  var messageCollection = threadsWithUnreadMessages.map(function(thread) {
    return thread.getMessages()
  })
  var unreadMessages = flatten(messageCollection).filter(function(message) { 
    return message.isUnread()
  })
  return unreadMessages
}

getUnreadMessages(100)