I have created a script which sends automated email based on cell values, created for an approval workflow.
Script is working fine, however, I am not able to prevent sending duplicate emails
Please help with some tips
//
var now = new Date();//mail semt date
var EMAIL_SENT = "EMAIL_SENT";// mail sent status
var approvalstatus = 'Approved';// Approved Status
function SecondaryApproval() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 100; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 16)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var Ticket = row[0];
var RequesterEmail = row[2];
var Item = row[3];
var emailAddress = row[6]; // First column
var message = row[7]; // Second column
var emailSent = row[8]; // Third column
var date = row[9];
var yesNo = row[5];
if (yesNo === approvalstatus) {
var subject = "Secondary Approval ";
GmailApp.sendEmail(emailAddress, subject, "Dear " + + "RequesterEmail" + Ticket + ", \n\nThis is an email report of your link. \n\nYour link is " + Item + " \n\nKind regards,\nName ", {
from: "Accounts#mydomain.com",
name: "Account"});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 9).setValue(now);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
else (emailSent === EMAIL_SENT); { // Prevents sending duplicates
}
}
You need to check for emailSent !== EMAIL_SENT before sending email:
//
var now = new Date();//mail semt date
var EMAIL_SENT = "EMAIL_SENT";// mail sent status
var approvalstatus = 'Approved';// Approved Status
function SecondaryApproval() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 100; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 16)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var Ticket = row[0];
var RequesterEmail = row[2];
var Item = row[3];
var emailAddress = row[6]; // First column
var message = row[7]; // Second column
var emailSent = row[8]; // Third column
var date = row[9];
var yesNo = row[5];
if (yesNo === approvalstatus && emailSent !== EMAIL_SENT) {
var subject = "Secondary Approval ";
GmailApp.sendEmail(emailAddress, subject, "Dear " + + "RequesterEmail" + Ticket + ", \n\nThis is an email report of your link. \n\nYour link is " + Item + " \n\nKind regards,\nName ", {
from: "Accounts#mydomain.com",
name: "Account"});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 9).setValue(now);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
Related
I have the a script to send emails and place a "Email_Sent" in a column to stop re-sends, what I an trying to do is have it enter todays date plus 7 days instead of "Email_Sent" so I can use if date = Today() for reminders this is the bit I am trying to change no avail this is what I have and the second snippet is what I need but work:
Working:
if (emailSent !== "EMAIL_SENT" && Send == "TRUE") {
var subject = 'Your Movie Link';
MailApp.sendEmail(emailAddress, subject, messagebody);
sheet.getRange(startRow + i, 8).setValue("EMAIL_SENT");
Change to this but not working:
if (emailSent == Today()) {
var subject = 'Your Movie Link';
MailApp.sendEmail(emailAddress, subject, messagebody);
sheet.getRange(startRow + i, 9).setValue(Today()+7);
Explanation:
To create a date after 7 days from today:
const dt = new Date()
dt.setDate(dt.getDate() + 7)
To use the following solution, you need to make sure that emailSent is a date object. Go to the sheet and use =isdate(A1). The latter will return TRUE if the value of A1 is indeed a date object. If it is a date object, then you can create a new Date() object. Namely, if emailSent is a date in your sheet, then you should be able to do: new Date(emailSent).
Solution:
function SendEmails() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Send Email');
var lastRow =sheet.getLastRow();
var startRow = 2;
var numRows = lastRow-1;
var dataRange = sheet.getRange(startRow, 1, numRows, 5000);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[1];
var Name = row[5];
var Amount = row[6];
var message = row[7];
var emailSent = row[8];
var subject = "Reminder fom spreadsheet";
messagebody = message.replace("{Name}",Name).replace("{Amount}",Amount)
ssTimeZone = SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone();
const dt = new Date();
if (Utilities.formatDate(new Date(emailSent), ssTimeZone, 'yyyy-MM-dd') == Utilities.formatDate(dt, ssTimeZone, 'yyyy-MM-dd')) {
dt.setDate(dt.getDate() + 7);
var subject = 'Your Movie Link';
MailApp.sendEmail(emailAddress, subject, messagebody);
sheet.getRange(startRow + i, 9).setValue(Utilities.formatDate(dt, ssTimeZone, 'yyyy-MM-dd'));
SpreadsheetApp.flush();
}
}
}
I got notification like this
Exception: Failed to send email: no recipient (line 19, file "Email")
I got no idea what happened
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 3; // First row of data to process
var getLastRow = 900; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, getLastRow, 6);
// 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 trigger = row[0]; // kolom ke 1 TRIGGER
var emailAddress = row[2]; // Email column
var message = row[4]; // Content column
var subject = row[3]; // Subject Column
var status_email = row[5];
if ((trigger != 'FALSE') && (status_email != 'EMAIL_SENT')) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 6).setValue('EMAIL_SENT');
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
You define getLastRow = 900 and emailAddress = row[2]
This means that from row 3 to row 900 you expect an email address to be present in each cell of column C
If you try to send an email from a row that does not contain an email address wou will get the error you metnioned
How to avoid the error?
Catch it with an if statement that checks either the cell is empty before sending the email
Sample
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 3; // First row of data to process
var getLastRow = 900; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, getLastRow, 6);
// 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 trigger = row[0]; // kolom ke 1 TRIGGER
var emailAddress = row[2]; // Email column
if(emailAddress != "" && emailAddress != " "){
var message = row[4]; // Content column
var subject = row[3]; // Subject Column
var status_email = row[5];
if ((trigger != 'FALSE') && (status_email != 'EMAIL_SENT')) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 6).setValue('EMAIL_SENT');
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
}
I am attempting to write a script to email employees account details after they have been hired. The script finally sends an email. and does not send duplicates. However it is not reading the information as expected across each row. I have no idea what is going on. I am also truly lost over the line
sheet.getRange(startRow + i-18,1).setValue(EMAIL_SENT);
at the bottom and why I had to put in the -18 in order to get the EMAIL_SENT written to the correct row in the sheet.
Here is the script:
var EMAIL_SENT = 'EMAIL_SENT';
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 55; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 9);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var subject = "MCS Account Info";
for (i in data) {
// clear variables between loops
var email1 = "";
var ccs = "";
var message = "";
var row = data[i];
var email1 = row[4];
if(row[4] !== "") var ccs = row[4];
if(row[5] !== "") var ccs = ccs + ", " + row[5];
if(row[6] !== "") var ccs = ccs + ", " + row[6];
if(row[7] !== "") var ccs = ccs + ", " + row[7];
var message = row[8];
// just so I can see what is in each variable will be removed when working
Logger.log("email - ",row[3],"subject - ",subject,"message - ",message,"bcc - ",ccs);
if (row[0] !== EMAIL_SENT) {
if(row[2] !== "") {
MailApp.sendEmail(row[3], subject, message, {
bcc: ccs
});
sheet.getRange(startRow + i-18,1).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
}
and a link to the test sheet I am using: https://docs.google.com/spreadsheets/d/1CzrMlsgwvkzp_w4IjZcOkSl7rU9T8qnBYBYi2luwWkg/edit?usp=sharing
In case the link does not work this is a sheet with 9 columns.
A - EMAIL_SENT message
B - # to look up info from another sheet
C - Username
D - User's Email address
E - H Additional Email Addresses for BCC
G - Message to send
Sheet will have several hundred entries as the year progresses right now I am looking at the first 56 rows even though my sheet only has 2 entries in it.
Try this:
function sendEmails() {
var sheet=SpreadsheetApp.getActiveSheet();
var startRow=2;
var numRows=55;
var dataRange=sheet.getRange(startRow,1,numRows,9);
var data=dataRange.getValues();
var subject="MCS Account Info";
for (var i=0;i<data.length;i++) {
var ccs="";
var row=data[i];
var email1=row[4];
if(row[4]!="") var ccs=row[4];
if(row[5]!="") var ccs=ccs + ", " + row[5];
if(row[6]!="") var ccs=ccs + ", " + row[6];
if(row[7]!="") var ccs=ccs + ", " + row[7];
var message=row[8];
if (row[0]!='EMAIL_SENT' && row[2]!="") {
MailApp.sendEmail(row[3], subject, message, {bcc: ccs});
sheet.getRange(i+startRow,1).setValue('EMAIL_SENT');
}
}
}
I have a Google Script running the sendEmails() function with the installable onChange trigger. This works well but I'm seeing that it also executes overnight, when no changes are made to the spreadsheet.
Anyone know what may be happening/ how to prevent this?
Here's the code that's running in the script editor:
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1; // Number of rows to process
// Fetch the range of cells A2:C2
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[4]; // Fifth column
var message = row[0]; // First column
var subject = row[3]; // Fourth Column
MailApp.sendEmail(emailAddress, subject, message);
}
}
In the executions/trigger log I see that a trigger executed last night at 5:07 am and the night before at 1:16am, when no changes were made to the spreadsheet
screenshot of trigger log
Wasn't able to figure out the underlying issue, but created code which prevents the script from sending an email (to Asana to create a task in this case) for any row where an email was previously sent.
var TASK_SENT= "TASK_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 UPDATE
var dataRange = sheet.getRange(startRow, 1, numRows, 48);
// 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 message = row[45] //Next Steps Column
var staff = row[1] // Your Name Column
var internal_part = row[7] //Who was the Check-in with? Column
var external_part = row[13] //What Site was your Check-in With? Column
var check_dt = row[2] //Date of Contact Column
var check_dt = Utilities.formatDate(new Date(), "GMT+1", "MM/dd/yy")
var site_disc = row[8] //What site was discussed?
var emailAddress = row[46]; // Email address column
var taskSent = row[47]; // Task_Sent column
if (taskSent != TASK_SENT) { // Prevents sending duplicates
var subject = staff + " " + 'check-in w/' + " " + internal_part + external_part + " " + 're:' + " " + site_disc + " " + check_dt + " " + 'Next Steps';
if (emailAddress == "") {
continue;}
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 48).setValue(TASK_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
Try this to see if it will eliminate the overnight emails.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 1;
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
var data = dataRange.getValues();
for (var i=0;i<data.length;i++) {
var row = data[i];
var emailAddress = row[4]; // Fifth column
var message = row[0]; // First column
var subject = row[3]; // Fourth Column
if(emailAddress && message && subject) {
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
I have a google spreadsheet that sends student information contained in a column that is queried and concatenated from another sheet. The queried information is separated by carriage returns. This column is then emailed to families triggered by a formula that calculates how many carriage returns should be in the cell.
That part I have taken care of in the sheet itself. I need assistance with emailing the column and maintaining the format of the cell. I've been able to do that with the code I have below, but it sends ALL of the data in column D in every email. I need it to only send what's located in the appropriate row for the email.
The main portion of the code that's giving me trouble, I think, is the following:
var OriginalString = SpreadsheetApp.getActive().getRange("D2:D").getValues();
var NewString = OriginalString.toString().replace(/\n/g, '<br>');
Any help would be appreciated!
function SendEmail3() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet3');
var startrow = 2;
var lastRow = ss.getLastRow();
var lastCol = 10;
var range = ss.getRange(2, 1, lastRow, lastCol);
var data = range.getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
var AccountName = row[0];
var email = row[1];
var Parent = row[2];
var Consent = row[4];
var StudentData = row[3];
var CarriageReturns = row[6];
var Trigger = row[7];
var emailSent = row[8];
var subject = "Your Application";
var OriginalString = SpreadsheetApp.getActive().getRange("D2:D").getValues();
var NewString = OriginalString.toString().replace(/\n/g, '<br>');
var message = "<HTML><BODY><font size=4>" +
"<P>" + "Hello " + Parent + ','
+"<BR>
+"<BR>" + NewString + "<BR>"
+"</HTML></BODY>";
var recipientsTo = email;
if (AccountName.length > 0 && Trigger >= CarriageReturns && emailSent != 'EMAIL_SENT') {
MailApp.sendEmail({
subject: subject,
to: recipientsTo,
htmlBody: message
});
ss.getRange(startrow + i, 9).setValue('EMAIL_SENT');
}
}
}
Is this what your looking for?
I set it up so that you can see the message on a modeless dialog rather than sending emails.
function SendEmail3() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet3');
var startrow = 2;
var lastRow = ss.getLastRow();
var lastCol = 10;
var range = ss.getRange(2, 1, lastRow, lastCol);
var data = range.getValues();
var html='';//Remove
for (var i = 0; i < data.length; i++) {
var row = data[i];
var AccountName = row[0];
var email = row[1];
var Parent = row[2];
var Consent = row[4];
var StudentData = row[3];
var CarriageReturns = row[6];
var Trigger = row[7];
var emailSent = row[8];
var subject = "Your Application";
var NewString = StudentData.split('\n').join('<br />');
//var message = "<HTML><BODY><font size=4>" + "<P>" + "Hello " + Parent + ',' + "<BR>" +"<BR>" + NewString + "<BR>" +"</HTML></BODY>";
var message=Utilities.formatString('<HTML><BODY><font size=4><P>Hello %s,<BR><BR>%s<BR></HTML></BODY>', Parent,NewString);
var recipientsTo = email;
if (AccountName.length > 0 && Trigger >= CarriageReturns && emailSent != 'EMAIL_SENT') {
//MailApp.sendEmail({subject: subject,to: recipientsTo,htmlBody: message});
html+=Utilities.formatString('%s- %s',i+1,message);//Remove
//ss.getRange(startrow + i, 9).setValue('EMAIL_SENT');
}
}
var userInterface=HtmlService.createHtmlOutput(html);//Remove
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Email Message');//Remove
}
Utilities.formatString()