Fail to Send an email with attachment using Google Apps Script - javascript

function SendEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Name List").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email Template").getRange(1, 1).getValue();
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 sent.");
} else {
for (var i = 2;i<=lr;i++){
var currentName = ss.getRange(i, 1).getValue();
var currentAppNo = ss.getRange(i, 2).getValue();
var currentEmail = ss.getRange(i, 3).getValue();
var messageBody = templateText.replace("{First Name}",currentName).replace("{App No}",currentAppNo);
var subjectLine = "CONGRATULATION ON YOUR VAL APPROVAL " + currentName
var attachmentBody = DriveApp.getFilesByName("THE ROOM SCRIPT.pdf");
MailApp.sendEmail(currentEmail, subjectLine, messageBody)
} //close for loop
} //close else statement
}
I have a Google Spreadsheet with a list of emails. I want to build a routine that sends email automatically to those email addresses. I also want to attach a PDF to this email. The PDF file is located on my Google Drive.
This does not seem to work

Here are two things that you may want to change in your script.
getFilesByName() gets a collection of files (as a FileIterator object) with that name. If there is just one such file, you'll need to change that line to
var attachmentBody = DriveApp.getFilesByName("THE ROOM SCRIPT.pdf").next; // To get the first such file
Ref doc here.
As #ross said, the sendMail() function needs to include the attachment like so:
MailApp.sendEmail(currentEmail, subjectLine, messageBody, {
attachments: [attachmentBody.getAs(MimeType.PDF)]
});
Ref doc here.

Related

MailApp.sendEmail Google Script Function

function onFormSubmit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("VSDTest");
var speedvsd = e.values[1];
Logger.log(speed);
if(speedvsd > 500 || speedvsd < 100){
var template = HtmlService.createTemplateFromFile("speedvsd");
template.speedvsd = speedvsd;
//template.recorded = recorded;
//template.remarks = remarks;
var email = 'someone#gmail.com';
var subject = 'Out of Range Notification';
var msg = 'Speed = '+speedvsd;
MailApp.sendEmail(email, subject, msg);
}
}
The code above does not get the email through. But with the same code changing MailApp.sendEmail(email, subject, msg) to MailApp.sendEmail("someone#example.com","Test Subject","Test Message") that actually works. My main goal is to collect responses from a Google Form. On certain columns, I have applied conditional formatting whereby if some data are above or lower than a certain value, it will trigger and send an email.
The issue here is I am not sure what causes it to not send through. I have created a trigger that will trigger upon form submit.
MailApp.sendEmail("someone#gmail.com",
"Out of Range Notification",
"",
{htmlBody : template.evaluate().getContent()});
I have also tried this and it didn't work.
edit: Now it works with the answer below. However, when I try to use var template = HtmlService.createTemplateFromFile(filename) and in my MailApp.sendEmail(email,subject,""{htmlbody: template.evaluate().getContent()}); this doesn't send me any email at all.
Try this:
function onFormSubmit(e) {
var speed = e.values[1];
Logger.log(speed);
if(speed){
var email = 'someone#gmail.com';
var subject = 'Testing‘;
var msg = 'Speed = '+speed;
MailApp.sendEmail(email, subject, msg);
}
}

How to set up sending automatic reminder emails linked to a questionnaire on Google Forms?

I have made a questionnaire using Google Forms. I have a set of emails (e.g. respondent1#example.com, respondent2#example.com, ...) as targets to send the questionnaire to. I receive the respondents' email address if they submit their responses. The responses can be saved in a google spreadsheet.
I would like to send a reminder email only to those who do not respond until a day after they received their email.
I am using the following code in the script.google.com that can send the email and works with a customized trigger in the G Suit Developer Hub. But it just sends a reminder email to all the emails listed in the following code. How can I add a condition to it that satisfies what I described?
function sendFormEmail() {
var emailAddress = "respondent1#example.com, respondent2#example.com";
var htmlMessage = HtmlService.createHtmlOutputFromFile("Reminder_email.html").getContent();
var subject = "Participation reminder";
var message = "Hi, please be reminded to submit your response";
MailApp.sendEmail(emailAddress, subject, message, {
htmlBody: htmlMessage
});
}
I managed to do it using two spreadsheets, one including the email of all participants, the other for the participants who have participated (extracted from the automatic spreadsheet made by Google Form when someone submits a response)
The function to send the reminder email is as follows. It can be triggered automatically using Google triggers embedded in the Google scripts.
Here is the code for the function I wrote.
function sendRemEmail()
// Load all the emails from the spreadsheet including all emails in the first column
{
var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/...').getActiveSheet();
var All_lr = ss.getLastRow();
var Alladdresses = [];
for (var i = 2; i<=All_lr;i++){
var emailAddress = ss.getRange(i,1).getValue();
Alladdresses.push(emailAddress);
}
// Load emails from the spreadsheet linked to the questionnaire
var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/...').getActiveSheet();
var sub_lr = ss.getLastRow();
var All_submitted_emails = [];
for (var i = 2; i<=sub_lr;i++){
var emailAddress = ss.getRange(i,2).getValue();
All_submitted_emails.push(emailAddress)
}
var rem_email_list = [];
for (var i = 0; i<=All_lr-1;i++){
if (All_submitted_emails.indexOf(Alladdresses[i])===-1){
rem_email_list.push(Alladdresses[i]);
}
}
var rem_email_list = rem_email_list.filter(function (el) {
return el != null;
});
Logger.log(rem_email_list);
var htmlMessage = HtmlService.createHtmlOutputFromFile("Reminder_email.html").getContent();
var subject = "Reminder";
var message = "Hi, please be reminded to submit your response";
for (var i = 0; i<rem_email_list.length;i++){
var emailAddress = rem_email_list[i];
MailApp.sendEmail(emailAddress, subject, message, {htmlBody: htmlMessage, from:'rzm#example.com', name: 'X Y',replyTo:'rzm#example.com'});
}
}
I have used a customized email (htmlMessage) written in HTML which is in the same project.

Script working when manually triggered but time trigger fails

I have a google script to add the data of the latest csv file in google folder below the last row of data in a mastersheet. The script works well when I run it manually, however when I set up a time trigger, the script fails with error message:
ERROR
No item with the given ID could be found, or you do not have permission to access it. at importData(Code:5)
My script is below. Can anyone assist? Thanks in advance.
function importData(folderID)
{
var ss = SpreadsheetApp.openById(my spreadsheet id);
var folderID = (typeof(folderID) !== 'undefined')? folderID : 'my folder id';//default folderID
var fldr = DriveApp.getFolderById(folderID);
var files = fldr.getFiles();
var dt = Utilities.formatDate(new Date(), Session.getScriptTimeZone(),"yyyyddMM");
var re =new RegExp('^' + "11286321_" + dt + '.*\.csv$','i');
while (files.hasNext())
{
var file = files.next();
var filename = file.getName();
if(filename.match(re))
{
var csvstr=file.getBlob().getDataAsString();
var csvData=Utilities.parseCsv(csvstr);
var sheet = ss.getSheetByName("EwayPayments");
var lastrow = sheet.getLastRow();
sheet.getRange(lastrow + 1, 1, csvData.length, csvData[0].length).setValues(csvData);
file.setName(filename.slice(0,-3) + 'old'); //the .old files won't pass the file re filter next time.
}
}
}

Create new spreadsheet with selected data from another sheet depending on the activeUser

first of all, this is the case:
I do have a masterdata sheet with lots of employee details (database). Column G contains email-adresses. I try to find a way to separate/select the lines for which the email-address matches the active user email-address. Without any opportunity for the user to change anything.
I tried different approaches with Query and IMPORTRANGE within the spreadsheet (e.g. =QUERY(IMPORTRANGE("101kbFw_DQGjmxhrw7BHK5-SM5IShkddre7GdqEhc2-U";"Data!A1:AC100"); "Select Col1,Col2,Col3,Col4 where Col7='Pascal Richter'"). But in this case the user would be able to change the name.
So I tried to build a webapp with the following functionalities:
the script identifies onOpen the activeUser
Button "send me data" starts the function createSSwithselectedData ()
the function createSSwithselectedData () creates a new spreadsheet
the function createSSwithselectedData () looks up the lines where the activeUser and the email in column g matches
the function createSSwithselectedData () transfers the identified data to the new spreadsheet
the activeUser gets an email with a link to the new spreadsheet
This is a dummy of the masterdata sheet.
Help is highly appreciated :)
// Log the email address of the active user
var email = Session.getActiveUser().getEmail();
Logger.log(email);
var DatabaseID = "101kbFw_DQGjmxhrw7BHK5-SM5IShkddre7GdqEhc2-U";
var Data = SpreadsheetApp.openById("101kbFw_DQGjmxhrw7BHK5-SM5IShkddre7GdqEhc2-U").getDataRange().getValues();
Logger.log(Data);
function doGet() {
var app = UiApp.createApplication();
// create a button and give it a click handler
var button = app.createButton("Send me data!").setId("button");
button.addClickHandler(app.createServerHandler("createSSwithselectedData"));
app.add(button);
return app;
}
function createSSwithselectedData(email) {
var app = UiApp.getActiveApplication();
app.getElementById("button").setText("Data is on the way");
return app;
var SheetTemplate = "1Z-ECGaRXaO8mEjTCx74z4sXOc_B7ZU81qfhtVJ3TAic";
var SheetName = "Jobgroup validation - ";
var newSheetName = SheetName + email ;
var folderId = "0B45D8-yA6A-HTWF1MjNhZW1VaXM"
var destination = DriveApp.getFolderById(folderId);
var copyId = DriveApp.getFileById(SheetTemplate).makeCopy(newSheetName, destination).getId();
var copySheet = SpreadsheetApp.openById(copyId);
// this is a new array to collect data
var target = new Array();
for(n=0;n<data.length;++n){ // iterate in the array, row by row
if (data[n][7]==email){ ; // if condition is true copy the whole row to target
target.push(data[n]); // copy the whole row
} //if
} //for
copySheet.getRange(1,10,target.length,target[0].length).setValues();
// Save and close the temporary document
copySheet.saveAndClose();
var url = copySheet.getUrl(); //DriveApp.getFileById(newFileId);
var link = "" + newSheetName + "";
var subject = "Jobgroup validation - " + email;
var body = "<p>You requested your team details. Please check the content.</p></br> " + link;
MailApp.sendEmail({to: email, subject: subject, htmlBody: body, name: alias, noReply: true});
}

createFile() in google Apps Script is not functioning properly

I am trying to create a file. It works fine when I run the following code segment from the debugger in apps script. However, when I run it real time from the spreadsheet, it says I do not have permission to call createfile. Everything that is logged is identical. The issue is not I do not have authority as I am the only one in the spreadsheet and am the owner. The purpose of the CSV is to move it from my google drive into data for BigQuery
function saveAsCSV(row) { //Doc to Csv
//row = 3; //when this is uncommented and ran from the debugger, it works.
try{
var fileName= Date.now()
fileName = fileName + ".csv";
var csvFile = convertRangeToCsvFile_(fileName,row);
Logger.log(csvFile); //Both times ran on the spreadsheet and from debug equals the same.
DriveApp.createFile(fileName, csvFile);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("New and Open").getRange("J" + row.toString()).setValue("");
loadCsv(fileName);
}
catch(e){Logger.log("B" + e.message);} //No permission to create file
}
function convertRangeToCsvFile_(csvFileName, r) {
var ws = SpreadsheetApp.getActiveSpreadsheet();
try {
//var data = ws.getValues();
var csvFile = undefined;
var csv = "";
var row = r;
var datArray = Create2DArray(1,19);
datArray[0][0] = ws.getRange("A" + row.toString()).getValue().toString().toUpperCase();
datArray[0][1] = ws.getRange("B"+row.toString()).getValue().toString().toUpperCase();
datArray[0][2] = ws.getRange("C"+row.toString()).getValue().toString().toUpperCase();
datArray[0][3] = ws.getRange("D"+row.toString()).getValue().toString().toUpperCase();
datArray[0][4] = ws.getRange("E"+row.toString()).getValue().toString().toUpperCase();
datArray[0][5] = ws.getRange("F"+row.toString()).getValue().toString().toUpperCase();
datArray[0][6] = ws.getRange("G"+row.toString()).getValue().toString().toUpperCase();
datArray[0][7] = ws.getRange("H"+row.toString()).getValue().toString().toUpperCase();
datArray[0][8] = ws.getRange("I"+row.toString()).getValue().toString().toUpperCase();
datArray[0][9] = new Date(ws.getRange("K"+row.toString()).getValue().toString()).getHours();
datArray[0][10] = new Date(ws.getRange("K"+row.toString()).getValue().toString()).getMinutes();
datArray[0][11] = new Date(ws.getRange("L"+row.toString()).getValue().toString()).getHours();
datArray[0][12] = new Date(ws.getRange("L"+row.toString()).getValue().toString()).getMinutes();
datArray[0][13] = new Date(ws.getRange("M"+row.toString()).getValue().toString()).getHours();
datArray[0][14] = new Date(ws.getRange("M"+row.toString()).getValue().toString()).getMinutes();
datArray[0][15] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getTime();
datArray[0][16] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getFullYear();
datArray[0][17] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getMonth();
datArray[0][18] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getDate();
for(var i = 0; i < 19; i++){
if(datArray[0][i] == ""){if(i > 9){datArray[0][i] = 0;} else{datArray[0][i] = "nil";} }
if(i < 18){csv += '"' + datArray[0][i] + '"' + ",";}
else{ csv += '"' + datArray[0][i] + '"'; }
}
Logger.log("A " + csv);
Logger.log(csv + "\n" + datArray[0].join(","));
csvFile = csv;
return csvFile;
}
catch(err) {
Logger.log("C" + err);
Browser.msgBox(err);
}
}
You mention in your comment on my answer that you are using onEdit to trigger the script. Since this is a Simple Trigger, your current approach will not work. When you use simple triggers to run an Apps Script, it runs in a sandbox with reduced permissions.
See: https://developers.google.com/apps-script/guides/triggers/#restrictions
The best I can recommend is create a custom menu option with a UI popup asking for the row number to export. If the code is triggered from a menu by the user, it runs with full permission to access that users account.
Depending on your use-case, a scheduled trigger might work too. It could run every 10 minutes or every Hour and export any changes to the spreadsheet. In this case the Apps Script runs as you, with permission to access your account, and the resulting CSV would be created on your drive.
Details on how to create a custom menu: https://developers.google.com/apps-script/guides/triggers/#onopen
Details on how to create a form for the user: https://developers.google.com/apps-script/guides/ui-service
Details on time driven triggers: https://developers.google.com/apps-script/guides/triggers/installable#time-driven_triggers

Categories

Resources