Count all eMails from a Label - google-apps-script

i have create this script:
function myTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var label = GmailApp.getUserLabelByName("Label1");
var threads = label.getThreads();
var countMail = 0;
//get first message in first thread
for (var i = 0; i < threads.length; i++) {
var messages=threads[i].getMessages();
countMail = countMail + messages.length;
}
ss.getRange(1,1).setValue(countMail);
}
it runs nearly perfect. Here I get all eMails back which are connected with this treads (marked with Label1 or not).
Does anyone can share a simply script how I can count all eMails which are "realy" marked with the Label.
Thanks

Try this:
function labelMsgs(){
var labels = Gmail.Users.Labels.list("me").labels;
var lblId;
for (var i = 0; i < labels.length; i ++){
if (labels[i].name == "Label1"){
lblId = labels[i].id;
break;
}
}
var optionalArgs = {
"labelIds" : lblId,
"maxResults" : 200
}
var messages = Gmail.Users.Messages.list("me", optionalArgs).messages;
}
This method uses the Gmail API directly, for this you'll need to enable Google Advanced Services, it will return a list of all messages tagged with the "Label1" label. You can play around with maxResults and with the pageToken to see more results, but this is the general approach.

Related

Define recipient depending on cell content

I made a script that forwards emails to different people when clicking on a card button. This is the main part of the code:
function forwardtest() {
var threadsa = GmailApp.search('label: Inbox label: product-a');
for (var i = 0; i < threadsa.length; i++) {
var recipient = 'producta#gmail.com';
var messages = threadsa[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient,{htmlBody: body});
}
GmailApp.moveThreadToArchive(threadsa[i]);
}
var threadsb = GmailApp.search('label: Inbox label: product-b');
for (var i = 0; i < threadsb.length; i++) {
var recipient = 'productb#gmail.com';
var messages = threadsb[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient,{htmlBody: body});
}
GmailApp.moveThreadToArchive(threadsb[i]);
}
}
Sometimes, we'll need to change the forwarding addresses. Since I don't want people to change it directly in the code, I made a Google Sheets in which the forwarding addresses are listed depending on the email labels:
Product label
Forward address
product-a
producta#gmail.com
product-b
productb#gmail.com
Is there a way to replace the var recipient = 'producta#gmail.com'; with "Look for the cell containing "product-a" content and define recipient as the content in the cell which is next to it"?
Thank you very much in advance!
Solution:
Since you will be referencing a Google Sheet to fetch the data, you would need to use Sheets API starting from the SpreadsheetApp class. Also, since this script is not attached to the sheet from your use case, you would need to open the sheet by it's ID, which is in the URL link:
https://docs.google.com/spreadsheets/d/<SHEET-ID>/edit#gid=0
Take note of the SHEET-ID since we will use it in the code.
For the code itself, I made a separate functions for finding the recipient and sending the emails for modularity:
EDIT: Rearranged the code, moved the function into a for loop instead.
function forwardtest() {
var sheet = SpreadsheetApp.openById("SHEET-ID").getSheetByName("Sheet1");
var prodList = sheet.getRange(2,1,sheet.getLastRow()-1,2).getValues();
for (var k = 0; k < prodList.length; k++) {
var prod = prodList[k][0];
var recipient = prodList[k][1];
var threads = GmailApp.search('label: Inbox label: '+prod);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var body = messages[j].getBody();
messages[j].forward(recipient,{htmlBody: body});
}
GmailApp.moveThreadToArchive(threads[i]);
}
}
}
Note: Replace the SHEET-ID with the sheet ID from the URL.
Sample Output:
Using a sample table with a variable number of products:
References:
Class SpreadsheetApp
Class Sheet
Class Range

Why doesn't this script collect all gmails?

I have a google app script that collects information about Gmail messages and then pastes it into a google sheet. Trouble is it doesn't get ALL of the messages. It only picks up the first one of each thread. I feel like I am missing something to loop through each thread? Any suggestions?
function getMail(){
var myspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mysheet = myspreadsheet.getSheetByName("Sheet3");
var start = 0;
var max = 99;
var count =0;
var row = mysheet.getLastRow()+1
var maxDate = mysheet.getRange("B1").getValue()
while(count < 4)
{
var threads = GmailApp.getInboxThreads(start , max);
var messages = GmailApp.getMessagesForThreads(threads);
var froms = [];
messages.get
for(var i = 0; i < threads.length; i++)
{
var msgDate = messages[i][0].getDate();
if(msgDate>maxDate){
froms.push([messages[i][0].getDate(),messages[i][0].getFrom(),messages[i][0].getSubject(),messages[i][0].getPlainBody()]);
}
}
if(froms.length>0){
mysheet.insertRows(2, froms.length)
mysheet.getRange(2,1,froms.length,4).setValues(froms);
}
start = start + 100;
count++;
}
}
Your current script is only grabbing messages[i][0], the first message in that group for the thread. Instead you need to loop through all of the messages using two for loops, as you can see in the script below I use messages[i][j].
function getMail() {
var mySpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mySheet = mySpreadsheet.getSheetByName("Sheet3");
var start = 0;
var max = 99;
var count = 0;
var maxDate = mySheet.getRange("B1").getValue();
while(count < 4) {
var threads = GmailApp.getInboxThreads(start, max);
var messages = GmailApp.getMessagesForThreads(threads);
var froms = [];
for(var i = 0; i < messages.length; i++) {
for(var j = 0; j < messages[i].length; j++) {
var msgDate = messages[i][j].getDate();
if(msgDate > maxDate) {
froms.push([msgDate,messages[i][j].getFrom(),messages[i][j].getSubject(),messages[i][j].getPlainBody()]);
}
}
}
if(froms.length > 0) {
mySheet.insertRows(2, froms.length);
mySheet.getRange(2, 1, froms.length, 4).setValues(froms);
}
start = start + 100;
count++;
}
}
Notable changes:
removed var rows because it wasn't used anywhere in the script.
changed first for loop to run for messages.length rather than
threads.
added another for loop to loop through every message in
messages[i].
you were getting messages[i][0].getDate() twice, so I just used the variable already defined for adding to the array.
minor grammatical/spacing changes for consistency across script.

google script maximum execution time - return google group emails (huge list)

Im trying to save google groups emails into a spreadsheet but Im getting the 'maximum execution time' error. Any ideas?
function listGroupMembers() {
var GROUP_EMAIL = "prgg#googlegroups.com";
var group = GroupsApp.getGroupByEmail(GROUP_EMAIL);
var users = group.getUsers();
var sheet = SpreadsheetApp.create("Group Mail");
for (var i = 0; i < users.length; i++) {
sheet.appendRow([users[i]]);
}
}
What is probably taking much of the time is the appendRow() call.
you should build an array with all the values and write this at once in your sheet.
Code could be like this :
function listGroupMembers() {
var GROUP_EMAIL = "prgg#googlegroups.com";
var group = GroupsApp.getGroupByEmail(GROUP_EMAIL);
var users = group.getUsers();
var sheet = SpreadsheetApp.create("Group Mail");
var values = [];
for (var i = 0; i < users.length; i++) {
values.push([users[i]]);
}
sheet.getRange(1,1,values.length, values[0].length).setValues(values);
}
EDIT
I didn't check the begining of your initial code, SpreadsheetApp.create("Group Mail"); returns a spreadsheet, not a sheet... that's why it fails on getRange.
Since it's not clear what you wanted to get exactly I assumed you wanted to create a new Sheet with that name if it doesn't exist.
The appropriate code would be like this :
function listGroupMembers() {
var GROUP_EMAIL = "prgg#googlegroups.com";
var group = GroupsApp.getGroupByEmail(GROUP_EMAIL);
var users = group.getUsers();
if(SpreadsheetApp.getActive().getSheetByName("Group Mail") == null){
var sheet = SpreadsheetApp.getActive().insertSheet("Group Mail");
}else{
var sheet = SpreadsheetApp.getActive().getSheetByName("Group Mail");
}
var values = [];
for (var i = 0; i < users.length; i++) {
values.push([users[i]]);
}
sheet.getRange(1,1,values.length, values[0].length).setValues(values);
}

GoogleScript Mail Parser - Only retrieve emails for past X days

Built a basic email parser so that I can get in gSheet my emails, however though, I have > 50k emails and I only need to retrieve them for the past 7 days each time I'll run the parser. Looked around but weren't able to find any similar issue
This is the script I have
var sheet = SpreadsheetApp.getActiveSheet();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
function getEmails() {
var label = GmailApp.getUserLabelByName("HOUSE_PHONELEAD");
var inc = 100;
var start = 0;
var row = 2;
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages=threads[i].getMessages();
for (var m=0; m < messages.length; m++) {
sheet.getRange(row,1).setValue(messages[m].getPlainBody());
row++;
Utilities.sleep(1000);
}
}
}
function onOpen() {
var menuEntries = [ {name: "Load Emails", functionName: "getEmails"} ];
spreadsheet.addMenu("Email", menuEntries);
}
Try to use
var threads = GmailApp.search('newer_than:7d');
instead of
var threads = label.getThreads();
search method allow to pass a string query :
https://developers.google.com/apps-script/reference/gmail/gmail-app#searchquery
the query string must be a gmail specific operator :
https://support.google.com/vault/answer/2474474?hl=en

Get message sender address from Gmail API

Let me preface my question by saying that I am not a JS dev, or even a web dev, so bear with me! I'm trying to create a gs script that deletes messages that are older than n months that have a certain label and are from a given sender.
I think I have it down, but the Gmail API getFrom() method seems to return the sender's address in the format "First Last" <address#mail.tld> rather than just address#mail.tld. Currently I can work around this by the fact that I know this information, but is there a better way of doing this so that the code operates solely on the actual email address?
My current code:
function auto_delete_emails() {
var label = GmailApp.getUserLabelByName("foo");
var sender = "\"Foo Bar\" <info#foo.bar>";
if (label != null) {
var delayDays = 30
var maxDate = new Date();
maxDate.setDate(maxDate.getDate() - delayDays);
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
var from = messages[0].getFrom();
if (from == sender) {
if (threads[i].getLastMessageDate < maxDate) {
threads[i].moveToTrash();
}
}
}
}
}
I have seen a question that used a regex to fix this, but I barely understand regex, never mind how to apply in this context or how the example worked (or didn't!).
Suggestions for other improvements on this code also welcome.
I think extracting the email address from the From-header is your safest bet. You can use e.g. this great RegEx:
function extractEmailAddress(header) {
return header.match(/[^#<\s]+#[^#\s>]+/)[0];
}
function auto_delete_emails() {
var label = GmailApp.getUserLabelByName("foo");
var sender = extractEmailAddress("\"Foo Bar\" <info#foo.bar>");
if (label != null) {
var delayDays = 30;
var maxDate = new Date();
maxDate.setDate(maxDate.getDate() - delayDays);
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
var from = extractEmailAddress(messages[0].getFrom());
if (from === sender) {
if (threads[i].getLastMessageDate < maxDate) {
threads[i].moveToTrash();
}
}
}
}
}