Send Email with Inline Image AND text in body - google-apps-script

I'm using this code to send emails that include an inline image and some text (both fetched from a sheets tab). The script runs well but the debug is not clean. Could you please help me find a better syntax?
The error I get is:
"Unexpected error while getting the method or property getBlob on
object DriveApp.File."
Thank you
function sendEmails() {
var ss = SpreadsheetApp.getActive().getSheetByName('SendMail')
var lr = ss.getLastRow();
var quotaLeft = MailApp.getRemainingDailyQuota();
//Logger.log(quotaLeft);
if((lr-1) > quotaLeft) {
Browser.msgBox("You have " + quotaLeft + " left and you're trying to send " + (lr-1) + " emails. Emails were not send.");
} else {
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 1).getValue();
var currentSubject = ss.getRange(i, 2).getValue();
var templateText = ss.getRange(i, 3).getValue();
var currentname = ss.getRange(i, 4).getValue();
var reply = ss.getRange(i, 5).getValue();
var image = DriveApp.getFileById(ss.getRange(i, 6).getValue()).getBlob();
var message = templateText.replace("{name}",currentname);
message += "<br/><br/><img src=\"cid:sampleImage\">";
//Logger.log(currentEmail);
MailApp.sendEmail({
to: currentEmail,
replyTo: reply,
subject: currentSubject,
htmlBody: message,
inlineImages: {sampleImage: image},
});
} //close for loop
} //close else statement
} //close sendEmails`

The error means:
No item with the given ID could be found, or you do not have permission to access it.
Or in other words:
ss.getRange(i, 6).getValue() does not contain a valid file ID.
For debugging purposes add the following two logs before retrieving the image and observe the results:
...
Logger.log("Cell: " + ss.getRange(i, 6).getA1Notation());
Logger.log("Image: "+ DriveApp.getFileById(ss.getRange(i, 6).getValue()));
var image = DriveApp.getFileById(ss.getRange(i, 6).getValue()).getBlob();
...
How to make sure the cell containing the image ID is not empty?
Implement an if statement verifying if the cell is blank. If so, continue with the next loop iteration:
...
if(ss.getRange(i, 6).isBlank()){
continue;
}
var image = DriveApp.getFileById(ss.getRange(i, 6).getValue()).getBlob();
...

Related

How to send email to only selected emails from google sheet?

new to google script, I have a google script with a button on the sheet which sends out emails from a google sheet, it works fine.
however I want to send emails to those emails that I checkmark manually, I have a column (F) with a checkmark, so I want to checkmark emails then send emails to those emails that have been check-marked only.
I stuck in the completion of the coding for the checkmark part, I appreciate your help.
I have commented out my 2 lines of code for filtering the checkmarks.
the code check for send email quote as well as writes timestamp and email sent note every time email has been sent.
Thanks.
these are columns, one header:
A1: timestamp
B1: email address
C1: Name
D1: Email Sent?
E1: Data emaill sent
F1: check box
function sendEmails(){
var sheet = SpreadsheetApp.openById("mySheetid");
var ss = sheet.getSheetByName("Emails");
var lr = ss.getLastRow();
var EMAIL_SENT = 'Email has been sent';
var messageSubject =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("BodyTextSheet").getRange(2, 1).getValue();
var messageText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubjectSheet").getRange(2, 2).getValue();
var quotaLeft = MailApp.getRemainingDailyQuota();
if ((lr-1) > quotaLeft){
Browser.msgBox("you have " + quotaLeft + "left and you're trying to send " + (lr-1) + "emails. Emails were not sent.");
} else{
for (var i = 2; i<=lr; i++){
var currentEmail = ss.getRange(i, 2).getValue();
var currentName = ss.getRange(i, 3).getValue();
var messageBody = messageText.replace("{name}",currentName);
//var selected = ss.getRange("F2:F" + ss.getLastRow()).getValues();
//data = selected.filter(function(r){ return r[6] == true});
MailApp.sendEmail(currentEmail, messageSubject, messageBody);
var EmailSent = ss.getRange(i, 4).setValue(EMAIL_SENT);
var TimeEmailSent = ss.getRange(i, 5).setValue(new Date());
SpreadsheetApp.flush();
}
}
}
This worked out when i tested it. In your code you have BodyTextSheet with the var: messageSubject and viseversa... This is a bit confusing. So you need to change those ranges in this code.
function sendEmails() {
const ss = SpreadsheetApp.openById("mySheetid");
const emailSheet = ss.getSheetByName("Emails");
const bodyText = ss.getSheetByName("BodyTextSheet").getRange(2, 1).getValue()
const subjectText = ss.getSheetByName("SubjectSheet").getRange(2, 2).getValue()
const emails = emailSheet.getDataRange().getValues();
const filterdRows = [];
for (i = 0; i < emails.length; i++) {
const row = emails[i]
if (row[5] == true) {
row.unshift(i+1)
filterdRows.push(row)
}
}
const quotaLeft = MailApp.getRemainingDailyQuota();
if (filterdRows.length > quotaLeft) {
Browser.msgBox(`you have ${quotaLeft} left and you're trying to send ${filterdRows.length} emails. Emails were not sent.`);
} else {
filterdRows.forEach(email => {
const messageBody = bodyText.replace("{name}", email[3]);
MailApp.sendEmail(email[2], subjectText, messageBody);
emailSheet.getRange(email[0], 4, 1, 2).setValues([['Email has been sent', new Date()]])
})
SpreadsheetApp.flush();
}
}
So i made some modifications:
const emails: Get all the emails at once (much quicker)
Loop over the data and check if column F (arrays are 0 indexed so column 5) is true
If is true then add i+1 (rownumber) to the beginning of the array
Then forEach filtertEmail send the mail and set set text and date in the right row (in one call) That is why i pushed the rownumber in the beginning.

Send Emails with or without Inline images depending on value in cell

Good afternoon. I'm using the code below to send emails with inline images retrieved by ID from a cell in spreadsheet. However, if the cell with the inline image ID is blank, the script does not send the message.
Is there a way to tweak this code to make it work in both cases? (with and without an ID value in cell)
Thanks
var ss = SpreadsheetApp.getActive().getSheetByName('SendMail')
var lr = ss.getLastRow();
var quotaLeft = MailApp.getRemainingDailyQuota();
//Logger.log(quotaLeft);
if((lr-1) > quotaLeft) {
Browser.msgBox("You have " + quotaLeft + " left and you're trying to send " + (lr-1) + " emails. Emails were not send.");
} else {
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 1).getValue();
var currentSubject = ss.getRange(i, 2).getValue();
var templateText = ss.getRange(i, 3).getValue();
var currentname = ss.getRange(i, 4).getValue();
var reply = ss.getRange(i, 5).getValue();
Logger.log("Cell: " + ss.getRange(i, 6).getA1Notation());
Logger.log("Image: "+ DriveApp.getFileById(ss.getRange(i, 6).getValue()));
var image = DriveApp.getFileById(ss.getRange(i, 6).getValue()).getBlob();
var message = templateText.replace("{name}",currentname);
message += "<br/><br/><img src=\"cid:sampleImage\">";
MailApp.sendEmail({
to: currentEmail,
replyTo: reply,
subject: currentSubject,
htmlBody: message,
inlineImages: {sampleImage: image},
});
} //close for loop
} //close else statement
} //close sendEmails```
This should do it.
The changes will also catch and an error that may occur if the image ID is incorrect or the file format is incorrect.
function sendMail(){
var ss = SpreadsheetApp.getActive().getSheetByName('SendMail')
var lr = ss.getLastRow();
var quotaLeft = MailApp.getRemainingDailyQuota();
//Logger.log(quotaLeft);
if((lr-1) > quotaLeft) {
Browser.msgBox("You have " + quotaLeft + " left and you're trying to send " +
(lr-1) + " emails. Emails were not send.");
} else {
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 1).getValue();
var currentSubject = ss.getRange(i, 2).getValue();
var templateText = ss.getRange(i, 3).getValue();
var currentname = ss.getRange(i, 4).getValue();
var reply = ss.getRange(i, 5).getValue();
var imageFile = ss.getRange(i, 6).getValue();
var image = ""
Logger.log("Cell: " + ss.getRange(i, 6).getA1Notation());
Logger.log("Image: "+ DriveApp.getFileById(ss.getRange(i, 6).getValue()));
if(imageFile){
try{
image = DriveApp.getFileById(imageFile).getBlob();
} catch (e) {
templateText += "<p>Image merge failed: " + e;
}
}
var message = templateText.replace("{name}",currentname);
message += "<br/><br/><img src=\"cid:sampleImage\">";
if(image){
MailApp.sendEmail({
to: currentEmail,
replyTo: reply,
subject: currentSubject,
htmlBody: message,
inlineImages: {sampleImage: image},
});
} else {
MailApp.sendEmail({
to: currentEmail,
replyTo: reply,
subject: currentSubject,
htmlBody: message,
});
}
} //close for loop
} //close else statement
} //close sendEmails```

Sending email using Google spreadsheet

I am creating a simple email notification using 2 conditions in Google spreadsheet. I created for I function so that it will scan the rows I needed for my if condition. If challengeStatus and challengeSent are met, it will send an email notification. The email works fine, however, every time I run the function, it won't be finished running the code. Looks like there is a problem with my loop statement somewhere but can't figure it out. Here is my code please help.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Challenges");
var lr= ss.getLastRow();
for (var i = 2;i<=lr;i++) {
var qaEmail = ss.getRange(i, 1).getValue()
var adminEmail = ss.getRange(i, 2).getValue()
var VideoId = ss.getRange(i, 3).getValue()
var QA1comment = ss.getRange(i, 10).getValue()
var QA2comment = ss.getRange(i, 11).getValue()
var QA3comment = ss.getRange(i, 12).getValue()
var challengeStatus = ss.getRange(i, 13).getValue()
var challengeSent = ss.getRange(i, 14).getValue()
var subject,mailbody
subject = "Challenge Result: ("+ VideoId + ")";
mailbody = 'Hi, ' +adminEmail+ ' <br><br>This email is to notify you that we have completed to process your dispute on Video Id: <b>' +VideoId+ '</b> and the result is <b>' +challengeStatus+ '</b>.<br><br> Scores will be updated based on the result. <br><br>Comments: <br><br> QA 1: ' +QA1comment+' <br><br>QA 2: ' +QA2comment+'<br><br> QA 3: ' +QA3comment+' <br><br>Thank you. <br><br>Quality Team';
if (challengeStatus =="Non Revert" && challengeSent ==""){
MailApp.sendEmail(adminEmail,subject," ",{
name: 'Quality Team (No Reply)',
cc: qaEmail,
htmlBody: mailbody,
});
//Logger.log(VideoId);
}
}
sendstatus = ss.getRange('N' + i).setValue('Sent')
}

Highlighting text in a google sheet cell using HTML and google apps script

I am relatively new to scripts and code and am trying to learn some new skills but what I need here is very confusing.
I have a script running which is essentially an independent mail merge. It references a cell in my google doc as a template, which has been formatted as HTML. In this template, I have a footer to the email which is a quote that I would like to be highlighted when the email is sent out.
Here is the script;
function sendEmail() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Emails").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var templateText =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("EmailTemplates").getRange(1, 1).getValue();
var quotaLeft = MailApp.getRemainingDailyQuota();
if((lr-1) > quotaLeft){
Browser.msgBox("You have " + quotaLeft + " email quota left for the day and you are trying to send " + (lr-1) + " emails. 0 emails were sent");
} else {
for (var i = 3;i<=lr;i++){
var currentEmail = ss.getRange(i, 4).getValue();
var SiteURL = ss.getRange(i, 5).getValue();
var FirstName = ss.getRange(i, 2).getValue();
var messageBody = templateText.replace("{{First Name}}",FirstName);
var subjectline = "Looking to partner with " + ;
var imageUrl = "place site url here"
var htmlBody = messageBody + "<br><img src='" + imageUrl + "'>";
MailApp.sendEmail(currentEmail, subjectline, messageBody, {htmlBody: htmlBody});
} // close for loop
} // close else statement
}
The footer of the email which I would like to be highlighted is this;
“Google only loves you when everyone else loves you first”
Is this possible?
+"<p style='color: purple'>Google only loves you when everyone else loves you first</p>";
This allowed me to change the text color only

attach multiple file types(pdf, xlsx) from Gdrive to email using appscript

I am trying to figure out a way to attach multiple types of files(pdf, xlsx) from drive to my emails using appscript. I have the below code which attaches .xlsx file type to emails based on the name of the file in a specific Gdrive folder.
So, i have a spreadsheet which has the following headers:
name, email address, header3, header4, status, filename
So basically i did a for loop to go through each line and attach the file mentioned in header: filename, to the email and it registers the header: status as "Email Sent".
I understand the logic behind, but not sure what or how to code in to make sure it picks up even if the file type is pdf, word, etc for different rows in the spreadsheet. I also am guessing that something needs to be done in
var email = GmailApp.sendEm.............................spreadsheetml.sheet")]});
the code:
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Info");
var lr = ss.getLastRow();
var email_Sent = "EMAIL SENT" // This constant is written in column 5 for rows for which an email has been sent successfully.
var dailyQuota = MailApp.getRemainingDailyQuota();
var alias = GmailApp.getAliases();
var replyTo = ss.getRange(1, 10).getValue();
if((lr-1) > dailyQuota) {
Browser.msgBox("Your daily quota is " + dailyQuota + " emails and you are trying to send " + (lr-1) + " emails." + " Hence the emails were not sent!!");
} else {
for (var i = 2;i<=lr;i++) {
var currentEmail = ss.getRange(i, 2).getValue();
var productPurchase = ss.getRange(i, 3).getValue();
var dueDate = ss.getRange(i, 4).getValue();
var currentName = ss.getRange(i, 1).getValue();
var emailSent = ss.getRange(i, 6).getValue(); //fetch if email has been sent or not
var fileName = ss.getRange(i, 5).getValue(); //fetch file name from column 6 from spreadsheet
var fileFromDrive = DriveApp.getFolderById("1oa2Yw3A7n4vbTKAgQVEfNjVxgBi0MaP8").getFilesByName(fileName); //fetch from drive by file name
if (emailSent != "EMAIL SENT") {
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1, 1).getValue(); //fetch template from sheet
var messageBody = templateText.replace("{name}",currentName).replace("{product}",productPurchase).replace("{date}",dueDate); //body of the message, replace with var in sheet "template"
var email = GmailApp.sendEmail(currentEmail, "Reminder: Payment due on " + productPurchase + " purchase", messageBody, {from: alias[0], replyTo: replyTo,
attachments: [fileFromDrive.next().getAs("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")]}); //send email with attachment
var cellUpdate = ss.getRange(i, 6).setValue(email_Sent); //to update column 5 once email sent
SpreadsheetApp.flush(); //to flush out pending actions on spreadsheet
} //close for if statement
Logger.log(cellUpdate);
} //close for loop statement
} //close else statement
Logger.log(dailyQuota);
}