Does anyone know how to customize the format of an email body in a script or within the cell formula when sending an email from google sheets?
The first attachment is the incorrect email body the script is sending
.
And the second attachment is the correct email body format I need the script to send
.
Code below:
// 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 = 1000; // Number of rows to process
// Fetch the range of cells A2:D1000
var dataRange = sheet.getRange(startRow, 1, numRows, 1000);
// 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 subject = row[3]; // Second column
var message = row[3]; // Third column
var emailSent = row[3]; // Fourth column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 4).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
Issue:
When plain text is added to the email body, a line break is added after ~78 characters, as you can see, for example, here: Gmail API - plaintext word wrapping.
To avoid this, you should add an HTML body instead of plain text, using MailApp.sendEmail(recipient, subject, body, options).
Also, you need to add HTML line breaks (<br>) if you want to maintain the line breaks from the cell value (\n). You can use String.prototype.replace() for that.
Solution:
Replace this:
MailApp.sendEmail(emailAddress, subject, message);
For this:
MailApp.sendEmail(emailAddress, subject, "", {
htmlBody: message.replace(/\n/g,'<br>')
});
Reference:
Gmail API - plaintext word wrapping
MailApp.sendEmail(recipient, subject, body, options)
String.prototype.replace()
Related
I have been trying to retrofit an old code I have used to send emails before to send an email when the formula solution in a cell equals today's date in another cell.
Here is my code:
function sendtest(e) {
var ss = e.source;
var s = ss.getSheetByName("Test");
var r = e.range;
// Below is the line that selects what column to use for the send date
var actionCol = 2;
var colIndex = r.getColumnIndex();
// Testing if statement
if (e.value == s.getRange(2, 3).getValue () && colIndex == actionCol) {
// All rows below are used to send the email
var row = r.getRowIndex();
// This takes the email addresses in column D
var userEmail = s.getRange(row, 4).getValue ();
//The subject line of the email
var subject = "Test test " + s.getRange(row, 1).getValue ();
//The structure of the body of the email
var body = "It has been two weeks since test test, " + s.getRange(row, 1).getValue ();
body +="\n\ntest test?";
body +="\n\ntest test,";
body +="\n\ntest test";
// This line sends the email
MailApp.sendEmail(userEmail,subject,body);
}
}
EDIT: Sorry I forgot to state what is going wrong. Every time I attempt to trigger this script (time based), I get an error telling me that line 3 (get sheet by name) is undefined.
I have a spreadsheet for recording customer samples. A column [I] is used to calculate when the original entry date is over a certain period which then displays an overdue message using an if statement. I want to trigger a script to check this column daily and if 'overdue' is found to send an email to an address contained in another column [C]. I am also using another column [J] to return a message when an email has been sent. I am using the script below but am returning errors
The script marks all rows in column J with the sent email message
I appear to be collecting a bigger array of data have needed [adding two rows the the bottom]
Anyone any ideas?
//Setup the function
function autoMail () {
var ss = SpreadsheetApp.getActiveSpreadsheet(); //Get the active spreadsheet
var sheet = ss.getSheetByName( 'TS_Requests' ); //Get the active spread
var startRow = 3; // Start of row that going to be process considering row 2 is header
var lastRow = sheet.getLastRow(); // Get the last row of data to be process
var lastColumn = sheet.getLastColumn(); // Get the last column of data to be process
var range = sheet.getRange(startRow,1,lastRow,lastColumn); //Getting the specific cell to be process
var data = range.getValues(); // Get the values inside the cell
for(var i=0;i<data.length;++i){
var row = data[i];
var email = row[2]; // Grab the email column. C in this case
var customer = row[3]; // Grab data for Email body
var item = row[5]; // Grab data for Email body
var description = row[6]; // Grab data for Email body
var status = row[8]; // Grab the column containing the value needed to be checked.
var EmailSent = row[9]
if (EmailSent != 'Email_Sent') { //Prevents e-mail being sent in duplicate
if(valstatus ='Overdue'){ // Check the values, if it's what's needed, do something
MailApp.sendEmail(email, 'Your sample request is overdue', customer + ' - ' + item + ' - ' + description); // if condition is met, send email
sheet.getRange(startRow + i, 10).setValue('Email_Sent');
}
}
}
}
So I am working on a Google Apps script that pulls an email address, subject, and body from a Google sheet file. This info is used to send an email out. Right now in my Subject column for the Google Sheets file I have =TODAY() so that the date is pulled. My script updates this column everyday so the date is always current.
The issue is that when the email comes the subject line shows
"Sat Aug 11 2018 00:00:00 GMT-0700 (PDT) "
Instead of...
08/11/18 like its setup for in Google Sheets
Not sure why this could be, My code is below.
/**
* Creates a two time-driven triggers.
*/
function createTimeDrivenTriggers() {
// Trigger every 6 hours.
ScriptApp.newTrigger('adddate')
.timeBased()
.atHour(21)
.everyDays(1)
.inTimezone("America/Los_Angeles")
.create()
ScriptApp.newTrigger('sendEmails2')
.timeBased()
.atHour(22)
.everyDays(1)
.inTimezone("America/Los_Angeles")
.create()
}
/**
* This is my hacky way to make sure sheets has today's date.
*/
function adddate() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var cell = sheet.getRange(2,2);
cell.setValue('=TODAY()');
}
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'SUCCESSFULLY 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 = 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 subject = row[1]; // Second column
var message = row[2]; // Third column
var emailSent = row[3]; // Fourth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
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();
}
}
}
The problem you are encountering is that your cell is formatted as a date and you are passing it as a parameter that expects a string. At that point you are no longer controlling the conversion, and you are getting way more than you wanted. Two ways to address it.
1) Make it a string in the first place with
cell.setValue('=text(TODAY(),"mm/dd/yy"');
which does run the risk of ruining any date processing you do on it at first (though I see none, so probably fine).
So probably better is (not 1, just this)
2) is to get the displayed string while leaving the underlying date like you had it with var subject = row[1].getDisplayValue();
2) has the added benefit of going with the date format for which sheets is set up.
I posted this question on Google Sheets forum and was directed here for help.
*Please note that I am not a coder, I've just started working with things like this.
I've created a workbook with 3 pages. It's connected to a form, so as people submit their reviews the answers are collected on the first sheet, calculated on the second sheet, and any submission with an overall score higher than 3.9 has the email address moved to the third sheet where it will be sent a follow-up email.
Here is a link to a copy of the sheet:
https://docs.google.com/spreadsheets/d/15p7_M4guRWCVHG-acRAheAROmh9t4wk3GWD_x0_rl90/edit?usp=sharing
It all works except the last page: I cannot figure out how to get the emails to send automatically as the sheet is updated. I've set the trigger to have it run when the sheet is updated, but to no avail - I have to manually go in and click the "Run" button to have the emails sent. (When I do, it pops up 'Failed to sent email: no recipient (line 21, file "Code")' but the emails are successfully delivered anyway.)
The formula I am using is this: (I have also tried swapping "sendEmails2" with "autoResponder" but that didn't change anything either.) Can anyone tell me what is wrong with it? Or is there a better way to automatically send the e-mails?
// 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 = 20000; // 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();
}
}
}
This should do it:
function sendEmails2(){
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Automatic Emails');
var rg=sh.getRange(2,1,sh.getLastRow(), 3);
var vA=rg.getValues();
for (var i=0;i<vA.length;i++){
var emailAddress = vA[i][0];
var message = vA[i][1];
var emailSent = vA[i][2];
var subject = "Sending emails from a Spreadsheet";
if(emailSent != 'EMAIL_SENT'){
MailApp.sendEmail(emailAddress, subject, message);
sh.getRange(2 + i,3).setValue('EMAIL_SENT');
}
}
}
Don't forget the onFormSubmit:
After taking a look at the provided tutorial for sending emails from a spreadsheet with Google Apps Script, I modified the given code with aims to be able to send the set of emails out with attachments as well.
It works well enough, even with a couple quirks from the limitations of Google Apps Script (the files have to be in the Google Drive, and all files in the Google Drive with whichever name is appropriate are taken from all folders in the drive).
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:C3
var dataRange = sheet.getRange(startRow, 1, numRows, 3)
// 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 attachment = row[2]; // File name provided.
var subject = "Mass Email";
var files = DriveApp.getFilesByName(attachment); // Get all files with name.
var blobs = []; // Array for attachment.
// Move files into blobs
while (files.hasNext()) {
var file = files.next();
blobs.push(file.getAs(MimeType.PLAIN_TEXT));
}
MailApp.sendEmail(emailAddress, subject, message, {
attachments: blobs, // add attachments
cc: "extra#email.com" // CC to employer
});
}
}
After I first used it, however, I learned that I need to send the files not as attachments, but as the message body of the emails, among some other changes (this is for work). That is, I will only ever email one 'attachment' at a time to each email, and instead of that file being an attachment, its content should be copied over to the message of the email. The attachments are currently text files, and I'd like them to stay that way, but it isn't the most vital thing.
I cannot determine a way to do this with Google Apps Script. Is this possible, or will I have to have a different way of emailing these files? (Hopefully not by hand.)
Try this. It's more faster and simpler.
var docContent = file.getBlob().getDataAsString();
Logger.log(docContent);
as mentioned in my last comment, converting your .txt files to Google documents makes it easy to achieve.
see below (suggestion)
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:C3
var dataRange = sheet.getRange(startRow, 1, numRows, 3)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
Logger.log(row)
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var attachment = row[2]; // File name provided.
var subject = "Mass Email";
var files = DriveApp.getFilesByName(attachment); // Get all files with name.
while (files.hasNext()) {
var file = files.next();
var Id = file.getId();
var content = DocumentApp.openById(Id).getBody().getText();
Logger.log(content)
MailApp.sendEmail(emailAddress, subject, message+'\n'+content)
}
}
}