Data is not written to Google Spreadsheet - google-apps-script

My script copies "unread" incoming messages from mail from the marked folder to the google table, and then marks it as read. But sometimes there are failures: the script is executed, marks the letters "as read", but does not write to the table. That is, in fact, it turns out in the logger there is a record with all the contents of these letters, but they are not written to the table. In theory, you need to check whether the data was written to the table and only then mark the letters "as read". Maybe there is an error in the code that periodically makes itself felt? Guys, help me, I'm just learning.
function GmailmarkReadEnd() {
//this is just the stuff that recognizes what spreadsheet you're in
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
/* searches your GMail for emails matching things "label:unread" + " label:support"
*/
var query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
if (query === "label:unread" + " label:support") {
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(SpreadsheetApp.getActiveSheet().getLastRow()+1,2,supportStats.
length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
// ***Sorting Recorded Data by Date***
sheet.getRange('D:D').activate();
sheet.sort(4, false);
}

function GmailmarkReadEnd() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
const query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(SpreadsheetApp.getActiveSheet().getLastRow()+1,2,supportStats.length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
sheet.sort(4,false);
}

Thanks to everyone who helped. If anything, read the comments.
function GmailmarkReadEnd() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
const query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(sheet.getLastRow()+1,2,supportStats.length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
sheet.sort(4, false);
}

Related

Google script to auto populate a form with conditional logic failing due to variable not being defined (even though it looks defined to me)

Below is a script written by Jordan Rhea and provided via github.
I am trying to follow its logic so that I can understand how to approach automatically populating a form with questions that have conditional logic flowing to different sections of a Google Form.
The code is breaking at line 35 "ReferenceError: form is not defined (line 35, file "RosterMaker")
Line 35 = var classSection = form.addPageBreakItem().setTitle(className).setGoToPage(FormApp.PageNavigationType.SUBMIT);
I'm sure this is a simple error, but I cannot figure it out.
var ssID = "something";
var formID = "something"
//SpreadsheetApp.openById(ssID).getSheetByName("db_type");
function rosterMaker() {
//spreadsheet id of the rosters
var SHEET_ID = SpreadsheetApp.getActive();
var ss = SpreadsheetApp.openById(ssID);
var form = FormApp.openById((formID));
//get only the sheets with 'Roster' in the title
var sheets = ss.getSheets()
.filter(function(sheet) {return sheet.getName().match(/Roster/gi);});
//add multiple choice item
var classSelect = form.addMultipleChoiceItem()
.setTitle('Choose a class');
Logger.log(classSelect);
//get the class choices for the multiple choice item
var classChoices = getClasses(sheets);
//assign the choices to the classSelect variable
classSelect.setChoices(classChoices);
}
function getClasses(sheets) {
var classChoices = [];
for(var i = 0; i < sheets.length; i++) {
var className = sheets[i].getName();
var classSection = form.addPageBreakItem()
.setTitle(className)
.setGoToPage(FormApp.PageNavigationType.SUBMIT);
var students = getStudents(sheets[i]);
var studentSelect = form.addCheckboxItem()
.setTitle(className + ' absent')
.setHelpText('Select the students who are absent from this class');
var studentChoices = [];
for(var j = 0; j < students.length; j++) {
studentChoices.push(studentSelect.createChoice(students[j]));
}
studentSelect.setChoices(studentChoices);
classChoices.push(classSelect.createChoice(className, classSection));
}
return classChoices;
}
function getStudents(sheet) {
var studentValues = sheet.getDataRange().getValues();
var students = [];
for(var i = 1; i < studentValues.length; i++) {
students.push(studentValues[i].join(' '));
}
return students;
}
Test this:
var ssID = "something";
var formID = "something";
function rosterMaker() {
var SHEET_ID = SpreadsheetApp.getActive();
var ss = SpreadsheetApp.openById(ssID);
var form = FormApp.openById((formID));
var sheets = ss.getSheets().filter(function(sheet) {return sheet.getName().match(/Roster/gi);});
var classSelect = form.addMultipleChoiceItem().setTitle('Choose a class');
var classChoices = getClasses(sheets,form);//modified
classSelect.setChoices(classChoices);
}
function getClasses(sheets,form) {//modified
var classChoices = [];
for(var i = 0; i < sheets.length; i++) {
var className = sheets[i].getName();
var classSection = form.addPageBreakItem().setTitle(className).setGoToPage(FormApp.PageNavigationType.SUBMIT);
var students = getStudents(sheets[i]);
var studentSelect = form.addCheckboxItem().setTitle(className + ' absent').setHelpText('Select the students who are absent from this class');
var studentChoices = [];
for(var j = 0; j < students.length; j++) {
studentChoices.push(studentSelect.createChoice(students[j]));
}
studentSelect.setChoices(studentChoices);
classChoices.push(classSelect.createChoice(className, classSection));
}
return classChoices;
}
function getStudents(sheet) {
var studentValues = sheet.getDataRange().getValues();
var students = [];
for(var i = 1; i < studentValues.length; i++) {
students.push(studentValues[i].join(' '));
}
return students;
}

Get email details based on the dates in google sheets

I am using the below mentioned apps script to get the email details in google sheets based on the label name updated in the particular cell.
function getBaEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var ss = sheet.getSheetByName("Raw Data");
var row = 2;
ss.getRange(2, 1, ss.getMaxRows() - 1, 4).clearContent();
var label = ss.getRange("F1").getValue();
var pattern = ss.getRange("F2").getValue();
var threads = GmailApp.search("in:" + label);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var msg = messages[m].getBody();
if (msg.search(pattern) !== -1) {
ss.getRange(row,1).setValue(
Utilities.formatDate(messages[m].getDate(),"GMT","MM-dd-yyyy"));
ss.getRange(row,2).setValue(messages[m].getFrom());
ss.getRange(row,3).setValue(messages[m].getSubject());
var id = "https://mail.google.com/mail/u/0/#all/"
+ messages[m].getId();
ss.getRange(row,4).setFormula(
'=hyperlink("' + id + '", "View")');
row++;
}
}
}
};
I am trying to update the apps script which helps to get the email details based on the dates.
For example : I need a email details from 08/01/2019 to 08/30/2019.
It would be great, if anyone help me to update the apps script.
Thanks in advance.
Try something like this:
You can always test your queries in Gmail
function gmailSearch(label,after,before) {
var label=label||'qs-vendors-google';
var after=after||'2019/01/01';
var before=before||'2019/08/01';
var html='';
var qry=Utilities.formatString('label:%s after:%s before:%s',label,after,before);
var results=GmailApp.search(qry);
for(var i=0;i<results.length;i++) {
var msgs=results[i].getMessages()
for(j=0;j<msgs.length;j++) {
html+=Utilities.formatString('<strong>Date:</strong> %s <strong>From: </strong> %s <strong>Subject: </strong> %s<br />',msgs[j].getDate(),msgs[j].getFrom(),msgs[j].getSubject());
}
}
var userInterface=HtmlService.createHtmlOutput(html).setWidth(1000);
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Search Results')
}

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

Stop recording to spreadsheet if Gmail Label exist

I like to record an email's Subject/Sender/Date/ID into a spreadsheet by it's label and add a "Recorded" label to the email once it's recorded into the spreadsheet. I like to run the script again without re-recording emails with the label "Recorded"
I can get it to the point of recording to spreadsheet and adding the label. but everything i run the script it grabs everything again.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var searchlabel = GmailApp.getUserLabelByName("Test");
var newlabel = GmailApp.getUserLabelByName("Recored");
var threads = searchlabel.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
var sub = messages[j].getSubject();
var from = messages[j].getFrom();
var dat = messages[j].getDate();
var id = messages[j].getId();
var current = new Date();
ss.appendRow([current, dat, sub, id, from])
}
threads[i].addLabel(newlabel);
}
}
I've search the forum and everything tends to suggest to remove the existing label and rename to a different label. But what i wantenter code here is to keep the existing label.
You should the search method since it lets you filter emails that belong to a particular label. Here's the modified version.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var searchlabel = GmailApp.getUserLabelByName("Test");
var recordlabel = GmailApp.getUserLabelByName("Recorded");
var threads = GmailApp.search("label:Test -label:Recorded");
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
var sub = messages[j].getSubject();
var from = messages[j].getFrom();
var dat = messages[j].getDate();
var id = messages[j].getId();
var current = new Date();
ss.appendRow([current, dat, sub, id, from])
}
threads[i].addLabel(recordlabel);
}
}
You can try replacing var threads with:
var threads = GmailApp.search('label:(Test -Recored)');
This searches for all labels with Test but not Recored.
You wouldn't need var searchlabel anymore.

Gmail apps script reading mailer-daemon messages

I would like to scan all my emails in Gmail, and extract only the mailer-daemon messages (to identify rejected email addresses).
When I'm using these methods, None of the mailer-daemon messages are returned - only the "valid" messages:
var ss = SpreadsheetApp.openById("1e29xgV1UU63SJEwF2aWQpWpcXMxyiylwEMGbuvbwADw");
var sheet = ss.getSheetByName("Email Addresses");
var row = 1;
sheet.getRange(row,1).setValue("Email Addresses");
row++;
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0 ; j < messages.length; j++) {
var txtBody = messages[i].getPlainBody();
var txtSender = messages[i].getFrom();
sheet.getRange(row,1).setValue(txtBody);
sheet.getRange(row,2).setValue(txtSender);
row++;
}
}
What can I use to process the mailer-daemon messages from the Mail Delivery Subsystem?
Thanks!
You should match the FROM: field of the message, something like:
var txtSender = messages[i].getFrom();
if (txtSender.indexOf("mailer-daemon") !== -1) {
// Log the entry in the spreadsheet
}
You should be filtering threads from the query itself, its more optimal (also paged).
function getBounced() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Bounced Addresses");
var row = 1;
var regExp = /[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}/i // "i" is for case insensitive
var threads = GmailApp.search('from:"mailer-daemon" subject:(failure|undeliverable)', 0, 50);
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0 ; j < messages.length; j++) {
var txtSubject = messages[j].getSubject();
var txtBody = messages[j].getBody();
var bouncedEmail = regExp.exec(txtBody)[0];
sheet.getRange(row,1).setValue(bouncedEmail);
sheet.getRange(row,2).setValue(txtSubject);
row++;
}
}
}
I also added a little code to extract the bounced/rejected email with a RegExp