Google Sheets keeps sending emails - javascript

Been building a landing page to start an email list. Decided to use Google Sheets as the backend to store emails & Google Scripts to send the first welcome message.
I hooked up an HTML page to Google Sheets with an API. The user submits their name & email, and then it goes to the Google Sheets. When the document is edited, this function gets triggered which sends a welcome message.
To prevent duplicate messages from going out, I put a simple system in place. When a user has been emailed, the third row (C) is filled in with "EMAIL_SENT" automatically.
When the function is triggered, it should only send the user an email if if there is no "EMAIL_SENT" but every time a new user submits their info, every single email on the list gets another welcome message.
I will attach an image of the spreadsheet
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow();
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var nameThisMan = row[1]; // Person's name
var emailSent = row[2]; // Third column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var message = "Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
var replyTo = "TechTimeDev#gmail.com";
var subject = "Welcome to TechTime's Email List";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

function sendEmails2() {
var sheet=SpreadsheetApp.getActiveSheet();
var startRow=2;
var numRows=sheet.getLastRow()-startRow+1;
var dataRange=sheet.getRange(startRow, 1, numRows, 3);
var data=dataRange.getValues();
for (var i=0; i < data.length; ++i) {
var row=data[i];
var emailAddress=row[0];
var nameThisMan=row[1];
var emailSent=row[2];
var replyTo="TechTimeDev#gmail.com";
var subject="Welcome to TechTime's Email List";
if (emailSent!='EMAIL_SENT') {
var message="Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue('EMAIL_SENT');
}
}
}

The method getLastRow() will return you the index of the last row with content. In the example you have provided this would be 3. However, what you actually want for performing getRange() is the number of rows you need to take. If you use three you would be taking an extra empty row and therefore, you would be getting the wrong values.
To change this to get the number of rows you need, you can simply do:
var numrows = sheet.getLastRow() - 1; instead of var numRows = sheet.getLastRow();
as you need to subtract from the index the number of rows you are not wanting to get in your range (in your case as you are ignoring the first row only 1 needs to be subtracted).

Related

Issue with static cc on Google's MailApp Script

Okay, so I'm working on a script that will basically pull information from a spreadsheet to then send out in an email once an email address is added into the spreadsheet. The issue is I'm trying to add a noReply and cc setting but it seems to then break my script to where it keeps sending emails or doesn't send any at all.
Theory: I think 'cc' is throwing the issue as the script is reading it as a recipient and just sending the email out instead of using the recipient that's added into the spreadsheet. This is the reference I'm following: https://developers.google.com/apps-script/reference/mail/mail-app#sendEmail(String,String,String,Object)
This is my code with the issue section being commented as such:
// This constant is written in column M for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 3; // Number of rows to process
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, 20);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[8]; // Column I
var message = ('For the ticket below, please ensure that you call the user as the first resort before following up via email.' + '\n\n TimeStamp: ' + row[1] + '\n Agent Name: ' + row[2] + '\n Your site: ' + row[3] + '\n Zendesk Link: ' + row[4] + '\n Summary of User Issue: ' + row[5] + '\n De-Escalation Attempted:' + row[6] + '\n User Contact Number ' + row[7]); // Fetch of columns B-H
var emailSent = row[12]; // Column M
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates and everything after && emailAddress is just testing a fix but didn't work
var subject = 'You have been assigned a Supervisor Call. Please Action Within 24 hours!';
MailApp.sendEmail(emailAddress, subject, message, { // Section below gives the issue
noReply: true,
cc: 'cc#email.com'
});
sheet.getRange(startRow + i, 13).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
Screenshot of spreadsheet layout:
enter image description here
This is my first time writing out a question on Stack but feel free to ask and I can detail more of what you need in order to help out.
I was able to get this working with Cooper's help. I had to do some small formatting changes to get it working but ultimately the code wasn't incorrect, just format issues that caused it to not be read appropriately.
Appreciate the help!

Failed redundancy measures on google script for sending emails via google sheets

I'm trying to send a reminder for a weekly webinar with emails that live on a Google Sheet using Google's script editor/codelab. The link for the tutorial it's based off of is here: https://developers.google.com/apps-script/articles/sending_emails
In their second section of code they post, it is an improved version because after the email is sent it populates a column with "EMAIL_SENT" and should prevent a duplicate email being sent out because "EMAIL_SENT" occupies that space (as I understand it).
My problem is that after I run the script, I'm able to get the emails to send off (I used three email accounts and each one received it), but I also get an error that reads:
Failed to send email: no recipient (line 24, file "macros").
Macros is the name of the file. The other issue I'm having is that if I run the script again after EMAIL_SENT has populated, it still sends an additional email even though it's not supposed to.
I've tried making the object in the first portion of the code different numbers to try and capture the right data. After I got the right data in there I don't understand why the other portions won't work.
`// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails_w_verification() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 116; // First row of data to process
var numColumns = 8;
var startColumn = 1;
// Fetch the range of cells as object
var dataRange = sheet.getRange(startRow, startColumn,
sheet.getLastRow(), numColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = "Thank you for registering for the webinar"; // Second
column
var emailSent = row[8]; // ninth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = 'AFWERX Webinar Reminder';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 9).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is
interrupted
SpreadsheetApp.flush();
}
}
}
Expected duplicates not to send and no error message of "Failed to send email: no recipient (line 24, file "macros")" when the email sent.
Your first no recipient error seems to be caused by how you're starting your for loop, if you switch it to i++ instead, the script runs fine. This is because by using ++i you're picking up an extra row which doesn't have any email address in it, causing it to throw the "no recipient" error you're getting.
The second issue with the script not being able to check against column 9 is because the range you defined is only 8 columns wide, not 9. I found this by using a simple Logger.log(emailSent) which came back as undefined, which is what you'd expect to see if the value isn't even being defined in the range at all.
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails_w_verification() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 1; // First row of data to process
var numColumns = 9;
var startColumn = 1;
// Fetch the range of cells as object
var dataRange = sheet.getRange(startRow, startColumn, sheet.getLastRow(), numColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = "Thank you for registering for the webinar"; // Second column
var emailSent = row[8]; // ninth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = 'AFWERX Webinar Reminder';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 9).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I've changed the for statement to use i++ rather than ++i which fixes the "no recipient" error message.
for (var i = 0; i < data.length; i++) {
Then changed your var numColumns to 9 rather than 8 so that it can see the column you're trying to check with your if statement.
var numColumns = 9;

In using this tutorial script from: https://developers.google.com/apps-script/articles/sending_emails can message column be changed dynamically?

In using this tutorial script from: https://developers.google.com/apps-script/articles/sending_emails
I am new to apps script and have been searching the forums trying to figure this out...
I'm trying to use another column in the spreadsheet to dynamically enter the salutation in the message. I thought it would be a formula like this:
="Dear "E2, + "Our 2018 Catalog is Coming Soon! Would you like a copy? " But, then I get the error that -ADD parameter1 is text and it is looking for numbers-, (even though I found it in another help area to use the quotes to separate the cell references).
So my questions:
1.Is it possible to make dynamic changes to the message in this script? Or do I need another script in the message column to do this?
2.If I am running more than one script on the spreadsheet and connected form do I need separate script files or just separate blocks on the same file
Thank you!
Adding a separate salutation to an email script
Here's the script for that tutorial:
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var emailSent = row[2]; // Third column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I believe you wish to have a separate salutation which is at the beginning of the message portion. It appears that you also wish to use column 5 for that data.
So if that's the case then your message would be something like this:
var message = Utilities.formatString('Dear %s\n%s',row[4],row[1]); Reference
This could also be accomplished this way:
var message = 'Dear ' + row[4] + '\n' + row[1];Reference
In either case you would put a name in column 5 and the rest of your message in column2. If you wan't to use html in your email replace the '\n' (line feed) with '<br />' (line break);
The message starts with the saluation in row[4] (column 5) and the rest of the message comes from row[1] according to the tutorial which is column 2.
The data from a getValues() command is returned in an array. Arrays index from zero where as columns in the spreadsheet begin at 1. Reference
If I misinterpreted your question please ask for further assistance in comments below. I'll be glad to help you.

Google Sheets - Script to Generate Paragraph in a Column

I've found a LOT of scripts that will take data from a Google Sheet and create a Google Doc, but I need a paragraph (really just a few sentences) generated into the Sheet itself. We create web pages for people who enter their information into a Google Form (name of their store, location, brands carried, etc.), we do this by exporting the Google Sheet into a .csv file, and uploading the file which generates the pages. So we need the paragraph to be in the Google Sheet.
I need a script that will give me a paragraph that says:
Column D is a "OUR BRAND" dealer located in Column H. Column D also sells Column T.
I've been trying to figure out this script for hours piecing together what I've found elsewhere and it seems like every time I sort out one bit, I screw up another bit. It's a mess:
function onEdit() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = activeSheet.getSheetByName("All Dealers");
var cell = sheet.getActiveCell();
var row = cell.getRow();
var col = cell.getColumn();
// Fetch the range of cells
var dataRange = sheet.getRange(row, col)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var dealerName = row[0]
var city = row[1]
var brand = row[2];
}
var body = 'dealerName' + "is a OURBRAND located in" + 'city' + 'dealerName' + "also sells" + 'brand';
SpreadsheetApp.getActiveSheet().getRange("AI"+row).setValue('body');
}
Spreadsheet is available here
You don't need a script for this: an arrayformula can do what you want.
Preliminary version: in cell AI2, enter
=arrayformula(D2:D & " is a BRAND dealer located in " & H2:H & ". " & D2:D & " also sells " & T2:T)
(Note that I've put spaces in appropriate places; this is something that requires extra attention when concatenating strings.)
The drawback of the above is that you also get some text in empty rows. To filter them out, replace each column reference by its filtered version: filter( ... , len(D2:D)) keeps only the rows with nonempty column D.
=arrayformula(filter(D2:D, len(D2:D)) & " is a BRAND dealer located in " & filter(H2:H, len(D2:D)) & ". " & filter(D2:D, len(D2:D)) & " also sells " & filter(T2:T, len(D2:D)))
This being in arrayformula means that as new data is added to columnds D,H,T, new text will be created in column AI.

If/Else Statement not working to send different emails

I am trying to write a script in google sheets that will send one of two different emails based on the response to a multiple choice question. I can get my if/else statement to send either one or the other of the emails but it will not recognize the text of the multiple choice answer and send the correct email.
Here is the full script:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1;
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 8)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var title = row[1]; // First column
var startDate = row[3]; // Second column
var endDate = row[4];
var description = row[2];
var location = row[6];
var eventImport = row[5];
var emailAddress = row[7];
var multchoice = row[8];
if (multchoice == "Part Time") {
var subject = "New Hire Part Time Email - " + startDate;
var emailBody = "Congradulations"
var htmlBody = "Congradulations! Part time person"
MailApp.sendEmail (emailAddress, subject, emailBody);
} else {
var subject = "New Hire Appointment - " + startDate;
var emailBody = "Congratulations! We are excited"
var htmlBody = "Congratulation! </i><br/> <br/> We are excited"
MailApp.sendEmail(emailAddress, subject, emailBody);
}
}
}
I believe the problem is here:
if (multchoice == "Part Time")
Any help is greatly appreciated! I am a novice
It looks like you are assigning your variables starting with '1' I stead of '0'. Start assigning them with 0 and counting up.
Without an example sheet to use, I won't be able to do a whole lot of debugging for you.
However, Apps Script comes with it's own debugger. Select the function you wish you debug and click the Little bug icon beside the play button.
Click on the sidebar where you want to set a breakpoint, where the code will stop executing.
Once it hits that breakpoint you can see all the variables currently within your scope. So the array, value, and i variables are visible to you.
Use this to your advantage and debug your code to find out where the issue is. Alternatively, you can use Logger.log() to log values at certain points within your code and then read back through the logs to try and determine where the problem lies.
The problem is not with your if/else statement. The problem is with how you are assigning your variables from your row[] array. While you use regular numbers in the getRange() function, the range that is returned is an array of those cells. Arrays always start with an index of [0]. Change var multchoice = row[8] to var multchoice = row[7] and your if/else statement will work (you'll want to change all of your other references, too).

Categories