Failed to send email: no recipient - google-apps-script

Good day! I need help in debugging this error: "Failed to send email: no recipient". The function sends emails based on the values of a range. Please check the code below.
function sendArticleCountEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Send-Emails"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(2, 1, sheet.getLastRow(), 5);
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var subject = 'DepEd Email/Account';
var FirstName = rowData[0];
var LastName = rowData[1];
var GeneratedEmail = rowData[2];
var Password = rowData[3];
var emailAddress = rowData[4];
MailApp.sendEmail({
to: emailAddress,
subject: subject,
htmlBody: '<h3>' + 'Good day Mr./Mrs./Ms. '+ FirstName + ' ' + LastName +'!</h3>' +
'<p>Here is your email/account (email and password):</p>' +
'<p><span style="background-color: #ffff00;"><strong><a name="gEmail">' + GeneratedEmail + '</a></strong></span></p>' +
'<p><span style="background-color: #ffff00;"><strong><a name="pword">' + Password + '</a></strong></span></p>' +
'<p>You can now login to mail.google.com to check your account.</p>' +
'<p>If you want to change password, login first then follow this link.</p>'
});
}
ss.getSheetByName('Form Responses 2').getRange(254, 12, sheet.getLastRow(), 1).copyTo(ss.getSheetByName('Form Responses 2').getRange(254, 14, sheet.getLastRow(), 1));
}
The function runs and sends all emails but then it gives the error. I suspect it loops to an empty row and can't find a recipient but I already have dataRange with sheet.getLastRow().

Often there will be a blank row returned at the end from a Range#getValues() call. We can add an if statement to skip sending if there is no data in a row:
function sendArticleCountEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Send-Emails"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(2, 1, sheet.getLastRow(), 5);
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
if(!rowData[4]) continue; //Skip this iternation if no email
var subject = 'DepEd Email/Account';
var FirstName = rowData[0];
var LastName = rowData[1];
var GeneratedEmail = rowData[2];
var Password = rowData[3];
var emailAddress = rowData[4];
MailApp.sendEmail({
to: emailAddress,
subject: subject,
htmlBody: '<h3>' + 'Good day Mr./Mrs./Ms. '+ FirstName + ' ' + LastName +'!</h3>' +
'<p>Here is your email/account (email and password):</p>' +
'<p><span style="background-color: #ffff00;"><strong><a name="gEmail">' + GeneratedEmail + '</a></strong></span></p>' +
'<p><span style="background-color: #ffff00;"><strong><a name="pword">' + Password + '</a></strong></span></p>' +
'<p>You can now login to mail.google.com to check your account.</p>' +
'<p>If you want to change password, login first then follow this link.</p>'
});
}
ss.getSheetByName('Form Responses 2').getRange(254, 12, sheet.getLastRow(), 1).copyTo(ss.getSheetByName('Form Responses 2').getRange(254, 14, sheet.getLastRow(), 1));
}
Alternatively, we can not grab the last row: var dataRange = sheet.getRange(2, 1, sheet.getLastRow()-1, 5);

Related

Email of specific data rang / table from Google Sheet

function B2B() {
var summary = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Summary");
var subject = "B2B - Delivery Status on";
var recipient = "******#***.in";
var dataRange = summary.getRange('B2:AA49');
var data = dataRange.getValues();
summary.getRange(2, 2, 25, 25).getValue;
var body = "I just discovered Apps Script and it's so cool!" + data;
MailApp.sendEmail(recipient, subject, body);
}
Used this query which is working and mail is going but, selected data range is table which i am not getting in table format in the mail.
Try this
function B2B() {
var summary = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Summary");
var subject = "B2B - Delivery Status on";
var recipient = "******#***.in";
var dataRange = summary.getRange('B1:AA49');
var [headers, ...rows] = dataRange.getValues();
MailApp.sendEmail({
to: recipient,
subject: subject,
htmlBody: "I just discovered Apps Script and it's so cool!" + "<br><br>" + tableHTML([headers], rows)
})
}
function tableHTML(headers, data) {
var tableformat = 'cellspacing="2" cellpadding="2" border="1" style="width:100%;border-collapse:collapse;border:1px solid #ccc"';
var header = headers.map(h => '<tr><th>' + h.join('</th><th>') + '</th></tr>')
var rows = data.map(r => '<tr><td>' + r.join('</td><td>') + '</td></tr>')
return '<table ' + tableformat + ' >\n' + header.join('\n') + rows.join('\n') + '</table>'
}
you need htmlbody instead of body
tableHTML is a function that will tranform the data into a table
map
join

How to Generate Gmail draft using Google App Script from Spreadsheet contains Table in the Body

I want to Generate a Gmail draft using Google App Script from Spreadsheet contains Table in the Body.
Below is the Screenshot of what input values I have and what type of output I want.
I shall be thankful if you could share the complete GS code, as I m new at Google App Scripts.
In Addition, I also want a Signature in the email Body, "Thanks and Regards" is my part of the body.
Also please note that Column E is dynamic, means may b it has 1 row and may be more than 1.
currently I am using this code.
function Email_Loop_BL() {
const signature = Gmail.Users.Settings.SendAs.list("me").sendAs.filter(function(account){if(account.isDefault){return true}})[0].signature;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var index = 2;
var index1 = 2;
var lastRow = sheet.getLastRow();
var data = sheet.getRange(1, 5, 10).getValues();
Logger.log(data)
for (;index1 <= data; index1++){
var message2 = sheet.getRange(index, 5, 1, 1).getValue();
}
var emailAddress = sheet.getRange(index, 1, 1, 1).getValue();
var ccmail = sheet.getRange(index, 2, 1, 1).getValue();
var subject = sheet.getRange(index, 3, 1, 1).getValue();
var message = sheet.getRange(index, 4, 1, 1).getValue();
//var location = sheet.getRange(index, 5, 1, 1).getValue();
//var guests = sheet.getRange(index, 6, 1, 1).getValue();
//var eventColour = sheet.getRange(index, 7, 1, 1).getValue();
//var sendInvites = true;
const html = "<div> </div><br>" + signature;
const options = {
htmlBody: message + data + html,
cc: ccmail
}
GmailApp.createDraft(emailAddress, subject, '', options);
}// End of Function
this is my input
this is my output I want.
function sendemail() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const rg=sh.getDataRange();
const vs=rg.getDisplayValues();
GmailApp.createDraft(vs[1][0].toString().split(/\n/).join(','),vs[1][2],'',{htmlBody:vs[1][3].toString().split(/\n/).join('<br>') + '<br>' + vs[1][4].toString().split(/\n/).join('<br>') + '<br>' + vs[1][5],cc:vs[1][1].toString().split(/\n/).join(',')});
}
My Data in Sheet1:
The Draft:
You can add more emails to recipients and cc by putting them on separate lines within the cell but terminating each line with a ctrl enter. Same is true with the invoices.

How to debug why a Google Script is not reading information from rows?

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

How do I add Email Sent to a status column and exclude those rows when the script runs again?

I am very new to scripting and am struggling to write a script for our youth league program's apparel fundraiser. The script, when triggered by clicking an image, will send an email to all of the recipients on a list, add 'email sent' to status column 'I' in all of the rows that the email sent to...then whenever the script is run again, only send emails to the new rows of data that haven't been emailed yet.
The script that I have inserts email sent, but if the script is run again it doesn't pay attention to the status column 'I' and I get duplicate emails. I've used tutorial videos to get me this far, but now I'm stuck. I've tried to get help from similar questions, but I'm not experienced enough to modify it to fit my needs. Here is a copy of the google sheet, the 'Send Emails' sheet has the info the script is running from. UPDATED:
https://docs.google.com/spreadsheets/d/1MBVhLj1A7Z_cpYxs_s5ae11ykJvTmS16E0jW4tGsNU4/edit?usp=sharing
function sendOrderEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Send Emails"));
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var dataRange = sheet.getRange("A2:I10");
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var rowData = data[i];
var emailAddress = rowData[0];
var recipient = rowData[1];
var message1 = rowData[2];
var parameter1 = rowData[3];
var message2 = rowData[4];
var message3 = rowData[5];
var parameter2 = rowData[6];
var message4 = rowData[7];
var emailSent = rowData[9];
var message = 'Hi ' + recipient + ',\n\n' + message1 + parameter1 + ' ' + message2 + ' ' + message3 + parameter2 + '. ' + message4 + '\n\n' + 'Tri-Valley Youth League Softball';
var subject = 'Order Reference Number ' + parameter2;
if (emailSent != "EMAIL_SENT" ) { // Prevents sending duplicates
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();
}
}
}
Try this:
function sendOrderEmails() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getSheetByName("Send Emails");
var startRow=2;
var dataRange=sheet.getRange("A2:J10");//Include column 10 in the range
var data=dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var rowData = data[i];
var emailAddress = rowData[0];
var recipient = rowData[1];
var message1 = rowData[2];
var parameter1 = rowData[3];
var message2 = rowData[4];
var message3 = rowData[5];
var parameter2 = rowData[6];
var message4 = rowData[7];
var emailSent = rowData[8];//This is column 9
var message = 'Hi ' + recipient + ',\n\n' + message1 + parameter1 + ' ' + message2 + ' ' + message3 + parameter2 + '. ' + message4 + '\n\n' + 'Tri-Valley Youth League Softball';
var subject = 'Order Reference Number ' + parameter2;
if (emailSent != "EMAIL_SENT" ) {
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 9).setValue("EMAIL_SENT");
}
}
}
I did this so that you can see the difference row and columns and data indices.
function rowsColumnsAndIndices() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getRange(1,1,26,26);
var vA=rg.getValues();
for(var i=0;i<vA.length;i++) {
for(var j=0;j<vA[i].length;j++) {
vA[i][j]=Utilities.formatString('r: %s, c: %s\ni: %s,j: %s', i+1,j+1,i,j);
}
}
rg.setValues(vA);
}

Prevents sending duplicates- is not working

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