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});
Related
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});
Disclaimer: I am new to programming so please bear with me :)
I am trying to send emails with a PDF file attachment to different email contacts on a Google Spreadsheet. Each attachment has to be unique to each Name by looking up that file name on google drive. Can someone help with that extra bit of code?
The code I have is currently sending emails with a custom message and a file attachment, and marking each email as sent in column C once the script ends running. However, I would like to send a different PDF attachment to each and every email address, ideally by writing some code that gets the "Investor Name" in column D, looks up the file in Google Drive that contains that name, and attaches that file to the email to be sent out.
So, I need to get the PDF file by each name in each corresponding cell, and not as written below (I believe):
var file = DriveApp.getFilesByName('SHARE CERTIFICATE #60 - JOHN APPLE.pdf');
// 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 = 250; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 250)
// 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";
var file = DriveApp.getFilesByName('SHARE CERTIFICATE #60 - JOHN APPLE.pdf');
if (file.hasNext()) {
MailApp.sendEmail(emailAddress, subject, message, {
attachments: [file.next().getAs(MimeType.PDF)],
name: 'Custom email Team'
});
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
}
The final result I expect is to:
- Send Emails to different email addresses with a message and subject
- Attach a PDF file with file name that correspond to the Name of each email recipient
Thanks a lot in advance, this will massively help! :)
Your code is missing a small detail. Basically, you should get the data from column D when using getRange:
var numRows = sheet.getLastRow() - startRow + 1; // Number of rows to process
var startCol = 1;
var numCols = 4; // Number of columns to process (should include column D)
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
Notice that the number of rows to be retrieved doesn't have to be hardcoded. If you use getLastRow you can get the index of the last row with content, and use that to get the desired range. This way you can get exactly the number of rows you want; not more, not less.
Then, inside the loop, retrieve the value in column D, like this:
var fileName = row[3]; // Fourth column
Finally, you retrieve the file from Drive like this:
var files = DriveApp.getFilesByName(fileName);
So the full modified code could be like:
// 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 = sheet.getLastRow() - startRow + 1; // Number of rows to process
var startCol = 1;
var numCols = 4; // Number of columns to process (should include column D)
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
// 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
var fileName = row[3]; // Fourth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
var files = DriveApp.getFilesByName(fileName);
if (files.hasNext()) {
var file = files.next();
MailApp.sendEmail(emailAddress, subject, message, {
attachments: [file], // No need to use getAs if your file is already a PDF
name: 'Custom email Team'
});
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 have made some additional small changes to that code (for example, changing the variable file to files and then defining var file = files.next()).
I hope this is of any help to you.
Something like this will work I think:
function sendEmails() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getActiveSheet();
var logsheet=ss.getSheetByName('logSheet');//added logsheet
if(!logsheet){ss.insertSheet('logSheet');}
var startRow=3;//added one row here to accomodate subject and pdfFldrId
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow()-startRow-1,sheet.getLastColumn())
var data = dataRange.getValues();
var subject= sheet.getRange("B2").getValue();
var pdfFldrId=sheet.getRange("C2").getValue();
for (var i=0;i<data.length;++i) {
var row=data[i];
var emailAddress=row[0];
var message=row[1];
var emailSent=row[2];
var pdfName=row[3];
var files=DriveApp.getFolderById(pdfFldrId).getFilesByName(pdfName);
var n=0;
while(files.hasNext()) {
var file=files.next();
n++;
}
if(n>1){
var ts=Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss");
logsheet.append([ts,pdfName,'more than file with this name']);
continue;//breaks out of loop increment index and keep going
}
if(emailSent!="EMAIL_SENT") {
MailApp.sendEmail(emailAddress, subject, message, {attachments:[file]});
sheet.getRange(startRow + i, 3).setValue("EMAIL_SENT");
}
}
}
If you want to send a different image with the same email list just duplicate the sheet and change the pdfFldrId and the subject which are found in C2 and B2 and learn to keep the different images is different folders with the same filenames.
I am very new to coding and I can't figuer out what I am doing wrong. I need 1 email sent from the last entry in my form. So as the students submit their pre-test they get an email that contains the result of their pre-test.
This is what my code looks like:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 3; // First row of data to process
var numRows = 1; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 3, 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[1]; // Second column
var message = row[2]; // Third column
var subject = "Résultat de formatif";
// This logs the value in the very last cell of this sheet
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var lastCell = sheet.getRange(lastRow, lastColumn);
Logger.log(lastCell.getValue());
MailApp.sendEmail(emailAddress, subject, message);
}
}
I do that by:
adding a separate column "STATUS" to the sheet
in your email sending function iterate over rows and act only on rows with "STATUS" being blank
after successfully sending email for a row, put something to the "STATUS" column
Please review the event object documentation.
You can install a "trigger" to automatically run your script on every form submission. Because this is triggered per submission, you don't need to worry about trying to find the last row or if the email had already been sent.
function sendEmails(formResponse) {
var answers = formResponse.values;
var emailAddress = answers[1]; // Second column
var message = answers[2]; // Third column
var subject = "Résultat de formatif";
// This logs the value in the very last cell of this sheet
var range = formResponse.range;
var row = range.getRow();
var column = range.getLastColumn();
try {
MailApp.sendEmail(emailAddress, subject, message);
} catch (e) {
console.error("Did not send email to " + emailAddress + ". See error: " + e);
range.getSheet().getRange(row, column+1).setValue("EMAIL NOT SENT");
return;
}
range.getSheet().getRange(row, column+1).setValue("EMAIL SENT");
}
I want to send emails from a spreadsheet to multiple people but only email them the information in all the columns and not just 1. For example, I want all the information from B2:E2 to be emailed to A2.
I am using the basic template provided in the Google Support which I have attached below.
All the changes to the code that I have made have not worked:
function sendEmails() {
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, 2)
// 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";
MailApp.sendEmail(emailAddress, subject, message);
}
}
There are quite few changes to make to the original script, html is our friend in this context, it will look nicer.
code :
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var colWidth = 5; // column width, including first one
// Fetch the range of cells A2:E3, one email per row
var dataRange = sheet.getRange(startRow, 1, numRows, colWidth)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var subject = "Sending emails from a Spreadsheet";
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = '<body><div style="font-family:arial,sans;font-size:10pt"><p>welcome message</p>';
message+= '<table style="border-collapse:collapse;" border = 1 cellpadding = 4><tr>';
for(var n=1 ; n<row.length ; n++){
message += '<td bgcolor="#EEF">'+row[n]+'</td>'
}
message += '</tr></table></div></body>';
MailApp.sendEmail(emailAddress, subject, 'html only',{htmlBody:message});
}
}
Sheet example :
email result , third row :
I have set up a spreadsheet which I think mimics the table structure you are looking for:
https://docs.google.com/spreadsheets/d/1S3fWaV4Sl4mIYjT-kMtOlP2V4xWSOpz721bxGWFuNqQ/edit
And the following function sends out emails:
One email per row
Email address in column 0, data in the other columns
Code:
// The range of data including email columns
// Example is set up with email in Column A, data in B and C
// Headers on Row 1, data rows on 2 and 3.
var DATA_RANGE = 'A2:C3';
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange(DATA_RANGE);
var values = data.getValues();
for (var i = 0, row; row = values[i]; i++) {
// Take email address from column A
var emailAddress = row[0];
// Join the remaining columns, comma-separated (as an example)
var messageData = row.slice(1).join(', ');
MailApp.sendEmail(emailAddress, 'Sending emails from a Spreadsheet', messageData);
}
}
Does this cover what you're trying to do?
I'm using a very basic automated email script. The message that I want to send out out is simply a date. In the spreadsheet this is formatted as "06/11/2013" but when the email is received it appears in the body of the email as "Wed Nov 06 2013 00:00:00 GMT-0000 (GMT)".
I want it to appear formatted in the body of the email as just the date as it is down in the spreadsheet. Is there any way to do this? Here is the (very basic) script I am using:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// 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 = "Date";
MailApp.sendEmail(emailAddress, subject, message);
}
}
Not a very advanced user but any help would be appreciated!
The data is stored in the spreadsheet as a Date and therefore will appear in the end content as Date. Use the Utilities.formatDate to convert this to a String
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// 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 = Utilities.formatDate(row[1], "GMT" , "dd/MM/yyyy" ); // Second column
var subject = "Date";
MailApp.sendEmail(emailAddress, subject, message);
}
}