sendEmail function in Google Sheets - google-apps-script

I have been struggling for days to get this appScript to function within my Google Sheets. Currently it is getting "stuck" on MailApp.sendEmail line, particularly on emailAddress. It gives me this error message "Invalid email: undefined". I based the majority of the script on their Sending Emails from a Spreadsheet Tutorial. So I'm not too sure where it might be going wrong.
Any help is much appreciated!
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh0 = ss.getSheetByName("Candidates Ready for Offer");
var startRow = 2; // First row of data to process
var numRows = ss.getSheetByName("Candidates Ready for Offer").getLastRow()-1;
// Fetch recent additions
var dataRange = ss.getSheetByName("Candidates Ready for Offer").getRange(startRow, 3)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[5];
var message = "row[1]" + "row [2]" + "at" + "row[4]" + "is ready for an offer!"
var subject = "Candidate is Ready for Offer";
MailApp.sendEmail(emailAddress, subject, message);
}
}

Thanks for sharing your sheet. There was actually a number of reasons why it wasn't working which I'll try and explain. Anyway, your script on the shared sheet will now function as you want it to. Here is what it looks like:
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh0 = ss.getSheetByName("Candidates Ready for Offer");
var startRow = 4; // First row of data to process
var numRows = sh0.getLastRow()-startRow+1;
// Fetch recent additions
var dataRange = sh0.getRange(startRow,1,numRows,6);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
Logger.log(data);
for (i in data) {
var row = data[i];
var emailAddress = row[3];
Logger.log(emailAddress);
var message = "row[1]" + "row [2]" + "at" + "row[4]" + "is ready for an offer!"
var subject = "Candidate is Ready for Offer";
MailApp.sendEmail(emailAddress, subject, message);
}
}
There's no need to keep calling the same sheet when you've already defined it as the variable sh0
The data range was including the first 3 rows. You didn't want this. Some simple maths in the var numRows allows the spreadsheet to only take the range containing data starting at row 4.
You were referencing the wrong column for email address. It was in column 4.
I hope this helps/makes sense.
Oli

The problem is your var dataRange. At the moment your code is only getting the range of one cell (startrow,3) instead of an array.
Replacing .getRange(startrow,3) with getDataRange() should fix your issue.

Related

Apps script email send with attachment based on a google drive url [duplicate]

I am using a mail merger script I found here, but I'm having trouble finding the right class to attach the file (rows 14 and 15).
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:B2
var dataRange = sheet.getRange(startRow, 1, numRows, 1)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[3]; // First column
var message = row[10]; // Second column
var subject = row[6];
var attachment = Attachment.setUrl(row[11]);
MailApp.sendEmail(emailAddress, subject, message, {attachments: attachment});
}
}
I've tried a handful of variations for the attachment function, but I've gotten an error each time. The rows correspond to columns in a Google Sheet, and row[11] is the URL for an image in google drive.
here is a working example of your script : you had 2 errors :
the range definition had only one column
the argument of attachment should be an array of blobs
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:B12 since you use row[11], the data must at least be 12 cells wide
var dataRange = sheet.getRange(startRow, 1, numRows, 12);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[3]; // Fourth column
var message = row[10]; // elevenths column
var subject = row[6];
var attachment = [UrlFetchApp.fetch(row[11]).getBlob()];
MailApp.sendEmail(emailAddress, subject, message, {attachments: attachment});
}
}
note also that url must be valid and that the file must be publicly shared : example :
https://drive.google.com/uc?export=view&id=0B3qSFd3iikE3TUFFLTc5MDE0MzkwLWQxYWItNDkwNy05ZjVkLWIyZDhiZDM4MjdmMg
Similar to Serge insas's answer, this is what I had to do in order to bypass the 401 error when using UrlFetchApp.fetch
var fileUrl = row[11] // Based on OP's case
var attachment = [
UrlFetchApp.fetch(fileUrl, {
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
}).getBlob(),
]
MailApp.sendEmail(emailAddress, subject, message, {attachments: attachment});

Google sheet SendEmail Script send a message to the same email address multiple times/ It hasn't happened untill today. Any way To solve it?

Stack overflowers!
I have a problem with my Sendemail Script, which is sending the same message for 8 times (really annoying, isn't it?) to each mail address. (It has been working fine until today though, I send remainders to five people daily; and my google sheet has two columns, one is for email address and the other is the message)
My code looks like this:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 5; // Number of rows to process
// Fetch the range of cells A2:B6
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[I];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'ATTENTION!!!!!!';
MailApp.sendEmail(emailAddress, subject, message);
}
}
How can I solve this annoying problem? (I am not a developer; I am just a learner who can use internet sources very well; So, I don't understand scripts much and still can edit or change it a bit.)
There is currently a bug with time-driven triggers
As a consequence, the trigger might fire multiple times - more frequent than you specify.
You can "star" the issue on Google's Issue Tracker to indicate that you are also concerned.
In the meantime, as a workaround:
Use Script Properties to save the last execution time
Implement an if statement at the beginning of your code that executes the rest of the code only if the last execution time (retrieved from the script properties) is not less than the specified interval
Sample:
function sendEmails() {
if(!PropertiesService.getScriptProperties().getProperty("lastExecution")){
PropertiesService.getScriptProperties().setProperty("lastExecution", new Date().getTime());
}
var lastExecution = PropertiesService.getScriptProperties().getProperty("lastExecution");
var now = new Date().getTime();
var oneDay = 1000*3600*24;
if(now-lastExecution >= oneDay){
//here the rest of you code
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 5; // Number of rows to process
// Fetch the range of cells A2:B6
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[I];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'ATTENTION!!!!!!';
MailApp.sendEmail(emailAddress, subject, message);
PropertiesService.getScriptProperties().setProperty("lastExecution", now);
}
}
}

how to send a whole sheet using MailApp.sendEmail

Trying to send the contents of a sheet1, A:R using the MailApp.sendEmail. I can't seem to figure out how to get the data to break after each row
I've tried to define the range based on last row and column
function sendEmails() {
var sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MissingInfo");
var Row = sheet.getLastRow()
var Col = sheet.getLastColumn();
var dataRange = sheet.getRange(1,1,Row,Col);
var data = dataRange.getValues();
var emailAddress = 'myemail#gmail.com';
var message = data
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
}
This works, except the data, doesn't break at the end of each row. any ideas on how to have a line break?
data is a 2D array. You can join row arrays using newlines \n:
var message = data.join('\n');

Attaching Google Sheet to emails from Gmail automatically using G Script

I found a G Script that works for sending an email to hundreds of addresses, based on an excel file with the name (which I can convert into Sheets if necessary).
I want to be able to add an attachment (which is currently an excel file, but can easily be converted into Sheets) to each email that is sent. The attachment is the same for each email.
The below script works for sending the emails, but I can't find the right way to add an attachment to each email (Note: line 17 is where I'm getting the error code).
I've tried a few different versions based on other similar strings on this site - but I can't get it to work with my situation, or maybe I don't understand how to structure the syntax accordingly.
/**
* 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:B2
var dataRange = sheet.getRange(startRow, 1, numRows, 1);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet'
var file = Drive.Files.get('test123/xlsx');
MailApp.sendEmail(emailAddress, subject, message, {attachments:
[file]});
}
}
ReferenceError: "Drive" is not defined. (line 17, file "Code")
"Drive" is the Advanced Drive API.In order to use the Drive advanced api you need to enable that api. But you really don't need the advanced api here.
Is your file in drive?
If so try this instead:
var file = DriveApp.getFileById("XXXXXXXXXXX");
the "xxx" should be the drive id.
According to the reference documentation, it looks like the class you're looking for is DriveApp.
/**
* 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:B2
var dataRange = sheet.getRange(startRow, 1, numRows, 1);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet';
var file = DriveApp.getFileById('test123/xlsx');
MailApp.sendEmail(emailAddress, subject, message, {attachments:
[file]});
}
}

How to ensure Script sends an email containing an HTML table with full range of data?

I have created a function that will allow me to send emails to a list of contacts via Google Sheets. The email will include a subject line and a table containing the data from my spreadsheet. The problem i am facing is that the HTML table is only sending the headers and 1 row of data. I can't find the error i have made.
The table will be ever increasing so i would like to email function to include all cells that have data in it. Is this possible?
I have adapted this Script/HTML code from How to format email from spreadsheet data using arrays? but i am now stuck with how to amend it further for my needs.
function testMail(){
var emails = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Contacts");
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A1:B1
var dataRange = emails.getRange(startRow, 1, numRows, 1);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var subject = "Current list of BGC 4 Acronyms";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var acronym = ss.getSheetByName("Sheet1");
var abbv = acronym.getRange("A5:A50").getValues();
var explan = acronym.getRange("B5:B50").getValues();
var message = composeMessage(abbv,explan);
var messageHTML = composeHtmlMsg(abbv,explan);
Logger.log(messageHTML);
MailApp.sendEmail(emailAddress, subject, message, {'htmlBody':messageHTML});
}
function composeMessage(abbv,explan){
var message = 'Here are the data you submitted :\n'
for(var c=0;c<explan[0].length;++c){
message+='\n'+abbv[0][c]+' : '+explan[0][c]
}
return message;
}
function composeHtmlMsg(abbv,explan){
var message = '<br><br><table style="background-color:lightblue;border-collapse:collapse;" border = 1 cellpadding = 5><th>Acronym</th><th>Explanation</th><tr>'
for(var c=0;c<explan[0].length;++c){
message+='<tr><td>'+abbv[0][c]+'</td><td>'+explan[0][c]+'</td></tr>'
}
return message+'</table>';
}
The expected result is an email sent to each address in the list with a subject line and full table of data. What i am actually getting is this
Try changing this:
for(var c=0;c<explan[0].length;++c){
message+='\n'+abbv[0][c]+' : '+explan[0][c]
}
To this:
I assume that abbv and explan are columns.
for(var c=0;c<explan.length;c++){
message+='<br />' + abbv[c][0]+ ' : ' + explan[c][0];
}
Try this:
function composeHtmlMsg(abbv,explan){
var message = '<br><br><table style="background-color:lightblue;border-collapse:collapse;" border = 1 cellpadding = 5><th>Acronym</th><th>Explanation</th><tr>'
for(var c=0;c<explan.length;c++){
message+='<tr><td>'+abbv[c][0]+'</td><td>'+explan[c][0]+'</td></tr>'
}
return message+='</table>';
}
Based upon your spreadsheet sample I think this could work:
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
var rg1=sh.getRange(5,1,sh.getLastRow()-4,1);
var rg2=sh.getRange(5,2,sh.getlastRow()-4,1);
var explan=rg1.getValues();
var abbv=rg2.getValues();