Send form to address based on response - google-apps-script

I have a Sheet that is linked with a basic Google form. I want to be able to select a name from the form and once submitted, it automatically send to an address based on the conditions I define.
E.g., if Ronald McDonald is selected in the form, then the script says that it should send to Ronald.mcdonald#example.com
The addresses are NOT within the form. - Just the names. I'd like the script to contain the addresses.
This is the first thing I'm attempting to build with app script. I can't find much online to figure out where to start.
Would very much like some help.
Sheet: https://docs.google.com/spreadsheets/d/1ZbUQ7HlY9BB3iKiLPcKAYnYry9EesvCzLs2zWz0PdMI/edit?usp=sharing
Form: https://docs.google.com/forms/d/19PmNlsFEHptmviafFgG6Qc077dOLXK8Yw1NOj3lJ7sk/edit?usp=sharing

Try first with this generic code
function onFormSubmit(e) {
var responses = e.namedValues;
if (responses["Agent Name"][0] == 'Ronald Mcdonald') {
MailApp.sendEmail({
to: '############gmail.com',
subject: 'new informations',
htmlBody: JSON.stringify(responses)
});
}
}
and put a trigger
edit
to take into account the list of emails, try (please initialize first to activate the trigger)
function initialize() {
if (ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "onFormSubmit").length == 0) {
ScriptApp.newTrigger("onFormSubmit")
.forSpreadsheet(SpreadsheetApp.getActive())
.onFormSubmit()
.create();
}
console.log('Your script has been initialized!')
}
function onFormSubmit(e) {
var responses = e.namedValues;
var email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Email contact')
.getDataRange().getValues()
.filter(r => r[0] == responses["Agent Name"][0])
if (email.length != 1) { return } // email found (unique)
MailApp.sendEmail({
to: email[0][1],
subject: 'new informations',
htmlBody: '<table cellspacing="2" cellpadding="2" border="1" style="border-collapse: collapse"><tr>' + Object.keys(responses).map(h => '<td>' + h + '</td><td>' + (Array.isArray(responses[h]) ? responses[h].join(",") : responses[h]) + '</td>').join('</tr><tr>') + '</tr></table>'
});
}

Try this:
function onFormSubmit(e) {
const eobj = {"Ronald McDonald":"Ronald.McDonald#example.com","Fred Smith":"foolish.freddy#jackass.com"};
if(eobj.hasOwnProperty(e.values[1])) {
GmailApp.sendEmail(eboj[e.values[1]],"Subject","Message")
}
}
function createOnFormSubmitTrigger() {
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "onFormSubmit").length == 0) {
ScriptApp.newTrigger("onFormSubmit").forSpreadsheet(SpreadsheetApp.getActive()).onFormSubmit().create();
}
}
You will have to fill in the eobj with all the the names as properties and values as email addresses.

As a supplement to the previous answers: When the script runs as a different (service) user the outgoing mail that is processed by apps script is labelled as sent by this very user identity. AFAIK there is no way to let the form respondent appear as the sender of the mail. The least you can do about it is setting the mail's alias and the reply-to with the responent's mail address like this:
let ffForm = FormApp.openById("123xcvdag71orwhatever");
let formResponses = ffForm.getResponses()[ffForm.getResponses().length -1];
let userMailAddress = formResponses.getRespondentEmail();
MailApp.sendEmail({
to: varWhoever,
subject: varSubject,
name: userMailAddress,
replyTo: userMailAddress}
);

Related

I'm trying to set up Apps Script to send emails for an Order Form from Google Sheets

I have created an Google Form so our employees can request their needs, it's a basic Order Form. I am receiving all their request in a Google Sheet and I'm trying to send them an email responding to their request. In my spread sheet I have a column called "Approval Status" with a drop down with the options "Approved", "Denied" and "Have Questions". What I'm trying to achieve is based on my "Approval Status" the person who made the request should receive an email with the response.
I've used the link below as reference. So far so good, until I get to step 5.3. I have tried editing the rows but I get a "ReferenceError: column is not defined". The error is coming from the shouldSendEmail function.
Here's my code and a picture of my spreadsheet.
Spreadsheet
function sendEmailsAndUpdateStatus() {
//Get the rows in the spreadsheet
var dataRange = SpreadsheetApp.getActive().getDataRange();
var data = dataRange.getValues();
//Remove the header row and add it to a new array.
//We will write this array back to the spreadsheet at the end.
var updatedData = [data.shift()];
//The variable numNotification will track if notifications were sent
var numNotifications = 0;
//Process each row using a forEach loop
data.forEach(function (row) {
//Check if email notifications should be sent and send them.
//If the notification is sent, increment numNotifications and also
//update the "Email sent" column to "Y".
if(shouldSendEmail(row)) {
sendApprovalStatusEmail(row);
numNotifications++;
row[9] = "Y";
}
//Add this row to the new array that we created above
updatedData.push(row);
});
//Write the new array to the spreadsheet. This will update the
//"Email sent" columns in the spreadsheet.
dataRange.setValues(updatedData);
//Display a Toast notification to let the user know if notifications
//were sent.
if(numNotifications > 0) {
SpreadsheetApp.getActive().toast("Successfully sent " + numNotifications + " notifications.");
} else {
SpreadsheetApp.getActive().toast("No notifications were sent.");
}
}
function shouldSendEmail(row) {
//Don't send email unless the expense report has been processed
if(column[7] != "Approved" && column[7] != "Rejected" && column[7] != "Have questions")
return false;
//Don't send email if email address is empty
if(row[5] === "")
return false;
//Don't send email if already sent
if(row[9] === "Y")
return false;
return true;
}
function sendApprovalStatusEmail(row) {
//Create the body of the email based on the contents in the row.
var emailBody = `
EXPENSE REPORT: ${row[7]}
-----------------------------------------------------------------
Note: ${row[8] === "" ? "N/A" : row[8]}
-----------------------------------------------------------------
Department: ${row[1]}
Amount: ${row[2]}
Reason: ${row[4]}
Date: ${(row[3].getMonth() + 1) + "/" + row[3].getDate() + "/" + row[3].getFullYear() }
-----------------------------------------------------------------
Please contact expensereports#example.com if you have any questions about this email.
`;
//Create the email message object by setting the to, subject,
//body, replyTo and name properties.
var message = {
to: row[6],
subject: "[Expense report " + row[7] + "]: " + row[4],
body: emailBody,
replyTo: "expensereports#example.com",
name: "Expense Reports"
}
//Send the email notification using the MailApp.sendEmail() API.
MailApp.sendEmail(message);
}

how do i email a quiz result from google forms using app script site

I need a Google script (GAS) to send an email where the student who passed the quiz on google forms can find his grade, for example if he passed the quiz and his grade is 10/10 he will receive an email on his address-email: "Hi, you've already passed your quiz and you got a 10/10"
Thank you
function sendEmail(e) { //respond //getRespondentEmail()
var html = HtmlService.createTemplateFromFile("email.html");
var htmlText = html.evaluate().getContent();
var emailTo = e.response.getRespondentEmail();
var subject = "Merci pour votre participation";
var textBody = "This email requires HTML support. Please make sure you open with a client that support it."
var options = { htmlBody: htmlText }; Logger.log(emailTo); if(emailTo !== undefined){ GmailApp.sendEmail(emailTo, subject, textBody, options);
}
}
Email Results of Quiz to respondent
From the Form Trigger
function onMyFormSubmit(e) {
const form = FormApp.getActiveForm();
const r = e.response;
r.getGradableItemResponses().forEach((item,i) => {
Logger.log('Question: %s Response: %s Score: %s',item.getItem().asTextItem().getTitle(),item.getResponse(),item.getScore());
});
let email = r.getRespondentEmail();
GmailApp.sendEmail(email,"Quiz Response",Logger.getLog())
Logger.log(r);
}
function createOnFormSubmitTrigger() {
const form = FormApp.getActiveForm();
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "onMyFormSubmit").length == 0) {
ScriptApp.newTrigger("onMyFormSubmit").forForm(form).onFormSubmit().create();
}
}
From the Spreadsheet Trigger
function onMyFormSubmit(e) {
Logger.log(JSON.stringify(e));
const ss = SpreadsheetApp.getActive();
const sh = e.range.getSheet();
const hA = sh.getRange(1,2,1,6).getValues().flat();
let s = '';
hA.forEach(h => {
s+= `\nQuestion: ${h} Answer: ${e.namedValues[h][0]}`
});
s += `\nYour Score is: ${e.namedValues.Score}`;
//Logger.log(s);
GmailApp.sendEmail(e.namedValues['Email Address'][0],"Quiz Result",s);
}
Email:
I believe your goal is as follows.
When the form is submitted, you want to send an email when the grade is 10/10.
From function sendEmail(e) { and var emailTo = e.response.getRespondentEmail();, your script is the container-bound script of Google Form. And, your function of sendEmail is installed as OnSubmit trigger.
Modification point:
In order to check if he passed the quiz and his grade is 10/10, it is required to calculate the grade of all items.
When this point is reflected in your script, it becomes as follows.
Modified script:
In this script, it supposes that the function sendEmail is run by the OnSubmit trigger. So please confirm whether the function sendEmail has already been installed as OnSubmit trigger again.
function sendEmail(e) {
var maxGrade = 10; // This is from "10/10" in your question.
var grade = e.response.getGradableItemResponses().reduce((p, e) => p += e.getScore(), 0);
var emailTo = e.response.getRespondentEmail();
if (grade < maxGrade || !emailTo) return;
var subject = "Sample subject"; // Please set the subject.
var textBody = "Hi, you've already passed your quiz and you got a 10/10.";
GmailApp.sendEmail(emailTo, subject, textBody);
}
Note:
From function sendEmail(e) { and var emailTo = e.response.getRespondentEmail();, I understood that your script is the conteiner-bound script of Google Form. So please be careful about this.
This modified script can be used by the OnSubmit trigger. So when you test this, please submit the form. When you directly run this script, an error occurs. Please be careful about this.
References:
Installable Triggers
reduce()

Mail merge Pre-filled Google form link

I use Google sheet and app scripts to create mail merge and it works fine with name, email, and general text information.
I am adding a column with a pre-filled Google Form link, like this.
Gmail Mail Merge Template
Although the mail merge works fine, the link does not work. the email recipient cannot click on the Google form link with pre-filled information.
Recipient's Mail Merge Results
What I'd expect to see is a Google Form hyperlink in the email body and the email recipient can click on it and be directed to the Google form with pre-filled information.
Is there a way to include pre-filled information too?
Example of the Google sheet used for mail merge.
Mail merge app script [From Google app script template]
const RECIPIENT_COL = "Email";
const EMAIL_SENT_COL = "Email Sent";
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Mail Merge')
.addItem('Send Emails', 'sendEmails')
.addToUi();
}
function sendEmails(subjectLine, sheet=SpreadsheetApp.getActiveSheet()) {
if (!subjectLine){
subjectLine = Browser.inputBox("Mail Merge",
"Type or copy/paste the subject line of the Gmail " +
" ",
Browser.Buttons.OK_CANCEL);
if (subjectLine === "cancel" || subjectLine == ""){
// if no subject line finish up
return;
}
}
// get the draft Gmail message to use as a template
const emailTemplate = getGmailTemplateFromDrafts_(subjectLine);
// get the data from the passed sheet
const dataRange = sheet.getDataRange();
const data = dataRange.getDisplayValues();
// assuming row 1 contains our column headings
const heads = data.shift();
const emailSentColIdx = heads.indexOf(EMAIL_SENT_COL);
const obj = data.map(r => (heads.reduce((o, k, i) => (o[k] = r[i] || '', o), {})));
// used to record sent emails
const out = [];
// loop through all the rows of data
obj.forEach(function(row, rowIdx){
// only send emails is email_sent cell is blank and not hidden by filter
if (row[EMAIL_SENT_COL] == ''){
try {
const msgObj = fillInTemplateFromObject_(emailTemplate.message, row);
GmailApp.sendEmail(row[RECIPIENT_COL], msgObj.subject, msgObj.text, {
htmlBody: msgObj.html,
//bcc: 'fusip#gmail.com',
//cc: 'fusip#gmail.com',
//from: 'fusip#gmail.com',
// name: 'fusip#gmail.com',
// replyTo: 'a.reply#email.com',
// noReply: true, // if the email should be sent from a generic no-reply email address (not available to gmail.com users)
attachments: emailTemplate.attachments
});
// modify cell to record email sent date
out.push([new Date()]);
} catch(e) {
// modify cell to record error
out.push([e.message]);
}
} else {
out.push([row[EMAIL_SENT_COL]]);
}
});
// updating the sheet with new data
sheet.getRange(2, emailSentColIdx+1, out.length).setValues(out);
function getGmailTemplateFromDrafts_(subject_line){
try {
const drafts = GmailApp.getDrafts();
const draft = drafts.filter(subjectFilter_(subject_line))[0];
const msg = draft.getMessage();
const attachments = msg.getAttachments();
return {message: {subject: subject_line, text: msg.getPlainBody(), html:msg.getBody()},
attachments: attachments};
} catch(e) {
throw new Error("Oops - can't find Gmail draft");
}
function subjectFilter_(subject_line){
return function(element) {
if (element.getMessage().getSubject() === subject_line) {
return element;
}
}
}
}
function fillInTemplateFromObject_(template, data) {
let template_string = JSON.stringify(template);
// token replacement
template_string = template_string.replace(/{{[^{}]+}}/g, key => {
return data[key.replace(/[{}]+/g, "")] || "";
});
return JSON.parse(template_string);
}
}
I would like to have the Google form link in the body of the email.
Issue:
You are filling your template with the actual text thus when sent in an email, it still has the exact value from the sheet.
Solution:
You need to convert your link properly using the built-in function encodeURI. I modified your function fillInTemplateFromObject_ and add a line there to use encodeURI as it will be the easiest way to fix the issue.
Code:
function fillInTemplateFromObject_(template, data) {
let template_string = JSON.stringify(template);
// convert your link into proper link using encodeURI
data['Google Form Link'] = encodeURI(data['Google Form Link']);
// token replacement
template_string = template_string.replace(/{{[^{}]+}}/g, key => {
return data[key.replace(/[{}]+/g, "")] || "";
});
return JSON.parse(template_string);
}
Output:
The easiest way to fix this problem is format your Google Form Link to "Plain Text"
I have a little issue with this samples too, I figure it out that the curly bracket {} from my keyboard different than the curly bracket {} this sample required. By changing the curly bracket, I've fixed my problem:
A picture from my email:
Create mail merge sample: Automate tasks with Apps Script:
https://developers.google.com/apps-script/samples/automations/mail-merge

Modifying the Google Spreadsheet script for sending values by email

This is an offshoot of a similar post here. A good answer was provided by Rivero but his code sends the values on the Google Spreadsheet's response sheet. I was wondering if instead the script would return values of the same row and column range specified by the code BUT from other sheet in the same spreadsheet. I'm really new to this and can't seem to find the right combination of codes to do so. Here is Rivero's code, I hope someone can help me accomplish this. Thanks in advance!
/* Send Confirmation Email with Google Forms */
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SendConfirmationMail")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function SendConfirmationMail(e) {
try {
var ss, cc, sendername, subject, columns;
var header, message, value, textbody, sender, itemID, url;
// This is your email address and you will be in the CC
cc = "name#email.com";
// This will show up as the sender's name
sendername = "name to be displayed as sender";
// Optional but change the following variable
// to have a custom subject for Google Docs emails
subject = "Choose an approppiate subject";
// This is the body of the auto-reply
message = "";
ss = SpreadsheetApp.getActiveSheet();
columns = ss.getRange(1, 1, 1, ss.getLastColumn()).getValues()[0];
// This is the submitter's email address
sender = e.namedValues["Username"].toString();
// Only include form values that are not blank
for ( var keys in columns ) {
var key = columns[keys];
//Use this to look for a particular named key
if ( e.namedValues[key] ) {
if ( key == "Username" ) {
header = "The user " + e.namedValues[key] + " has submitted the form, please review the following information.<br />";
} else {
message += key + ' ::<br /> '+ e.namedValues[key] + "<br />";
}
}
}
}
textbody = header + message;
textbody = textbody.replace("<br>", "\n");
Logger.log("Sending email");
GmailApp.sendEmail(cc, subject, textbody,
{cc: cc, name: sendername, htmlBody: textbody});
} catch (e) {
Logger.log(e.toString());
}
}
It would better if you can name your sheet and use it instead of using active spreadsheet.
var sheet = SpreadsheetApp.openById('spreadsheetId').getSheetByName('name');
OR you can also use the sheet number to access it.
var sheet = SpreadsheetApp.openById('spreadsheetId').getSheets()[0];
After you have reference to the sheet, get the range for the column followed by data array:
var columnRange = sheet.getRange('a1Notation');
var dataArray = columnRange.getValues();
then iterating the data as per your convenience
for(var i=1; i<=dataArray.length; i++)
{
}

Send email to specific user based on Google Form

Background: Google Script for Forms creating a phone message log that emails to a specific person as selected.
Need help with the email address portion of the code. I want to have a message sent to an email address based on the radio button with the person's name selected.
function Initialize() {
var triggers = ScriptApp.getScriptTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SendGoogleForm")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function SendGoogleForm(e) {
try {
var email = HELPHELPHELP;
// Optional but change the following variable
// to have a custom subject for Google Form email notifications
var subject = "Google Docs Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var columns = s.getRange(1, 1, 1, s.getLastColumn()).getValues()[0];
var message = "";
// Only include form fields that are not blank
for (var keys in columns) {
var key = columns[keys];
if (e.namedValues[key] && (e.namedValues[key] != "")) {
message += key + ' :: ' + e.namedValues[key] + "\n\n";
}
}
// This is the MailApp service of Google Apps Script
// that sends the email. You can also use GmailApp for HTML Mail.
MailApp.sendEmail(email, subject, message);
} catch (e) {
Logger.log(e.toString());
}
}
Presumably the intended recipient's name comes from a question / column with a title like "Message for".
In that case, try this:
...
var email = resolveEmail( e.namedValues["Message for"] );
...
function resolveEmail( userName ) {
// List of userNames & (secret) email addresses
var userEmails = {
"Mickey" : "bigears#example.com",
"Donald" : "duckman#example.com" // etc.
};
if (userName in userEmails) {
return userEmails[userName];
}
else {
// Unknown user - send email to script owner
return Session.getEffectiveUser().getEmail();
// Alternatively, could throw an error to get notified
// throw new Error( "Could not resolve email for user: " + userName );
}
}