I want to do a google form to send an email to the submitter, I used this code instruction using the app script method is as follows... form (submission) > sheet (responses) > app script > get a Doc file as email template > send email
my problem is on the submission app will send multiple emails duplicated. no matter what I do
this is app scripted was taken from here
enter link description here
var EMAIL_TEMPLATE_DOC_URL = 'https://docs.google.com/document/d/1M2n7iOkl4IeKmuTjU95ibQN6W6UqYtkA9d99fccPd_Y/edit?usp=sharing';
var EMAIL_SUBJECT = 'title';
/**
* Installs a trigger on the Spreadsheet for when a Form response is submitted.
*/
function installTrigger() {
ScriptApp.newTrigger('onFormSubmit')
.forSpreadsheet(SpreadsheetApp.getActive())
.onFormSubmit()
.create();
}
/**
* Sends a customized email for every response on a form.
*
* #param {Object} e - Form submit event
*/
function onFormSubmit(e) {
var responses = e.namedValues;
// If the question title is a label, it can be accessed as an object field.
// If it has spaces or other characters, it can be accessed as a dictionary.
var timestamp = responses.Timestamp[0];
var email = responses['Email Address'][0].trim();
var name = responses.Name[0].trim();
// If there is at least one topic selected, send an email to the recipient.
var status = 'Email Sent';
// Append the status on the spreadsheet to the responses' row.
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var column = e.values.length + 1;
sheet.getRange(row, column).setValue(status);
MailApp.sendEmail({
to: email,
subject: EMAIL_SUBJECT,
htmlBody: createEmailBody(name),
});
Logger.log('status=' + status + '; responses=' + JSON.stringify(responses));
}
/**
* Creates email body and includes the links based on topic.
*
* #param {string} name - The recipient's name.
* #param {string[]} topics - List of topics to include in the email body.
* #return {string} - The email body as an HTML string.
*/
function createEmailBody(name) {
// Make sure to update the emailTemplateDocId at the top.
var docId = DocumentApp.openByUrl(EMAIL_TEMPLATE_DOC_URL).getId();
var emailBody = docToHtml(docId);
emailBody = emailBody.replace(/{{NAME}}/g, name);
return emailBody;
}
/**
* Downloads a Google Doc as an HTML string.
*
* #param {string} docId - The ID of a Google Doc to fetch content from.
* #return {string} The Google Doc rendered as an HTML string.
*/
function docToHtml(docId) {
// Downloads a Google Doc as an HTML string.
var url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' +
docId + '&exportFormat=html';
var param = {
method: 'get',
headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
};
return UrlFetchApp.fetch(url, param).getContentText();
}
I tried to do this. to check if the last column is empty before sending an email. after sending, it will be failed with Email Sent, my thing is will limit the email duplication. but did not.
if(sheet.getRange(row, column).getValue() == "")
{
sheet.getRange(row, column).setValue(status);
MailApp.sendEmail({
to: email,
subject: EMAIL_SUBJECT,
htmlBody: createEmailBody(name),
});
}
I tried to do a count to see how many emails does it send. the last cell shows 0 and it sent duplicates emails.
if(sheet.getRange(row, column).getValue() == "")
{
sheet.getRange(row, column).setValue(0);
}
else
{
sheet.getRange(row, column).setValue(sheet.getRange(row, column).getValue + 1);
MailApp.sendEmail({
to: email,
subject: EMAIL_SUBJECT,
htmlBody: createEmailBody(name),
});
}
EDIT
after using this...
ScriptApp.getProjectTriggers().forEach(trigger => Logger.log(trigger.getHandlerFunction() + ' - ' + trigger.getEventType()))
this is what I got
As Cooper mentioned in the comment, you might have installed more than 1 trigger.
You can check your project's triggers page to view duplicates, or run this line.
ScriptApp.getProjectTriggers().forEach(trigger => Logger.log(trigger.getHandlerFunction() + ' - ' + trigger.getEventType()))
The line above will log like this if you have a duplicate trigger:
Just remove the duplicate ones and just have 1 of them remain so your mail should not send duplicate mails anymore.
Only 1 trigger should remain after deleting the duplicates in triggers page:
Reference:
ScriptApp
Related
I'm trying to create code that will send an email using addresses from a specific column in google sheets. I want the code to send an email after the sheet is edited by other users. For example, someone enters a request on a row in the sheet - then an email is sent to the manager of the request. Here's what I have so far...
function SendEmail(){
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("HLP REQUESTS").getRange("K:K");
var emailAddress = emailRange.getValues()[0][0];
// Send Alert Email.
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.'; // Second column
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message);
}
When I run the code above I get an error - Exception: Failed to send email: no recipient. There is a valid email address in column K, so I'm a little confused.
If you want get email address from the last cell of the column K it can be done this way:
function SendEmail(){
var emailRange = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName("HLP REQUESTS").getRange("K:K");
var emailAddress = emailRange.getValues()
.flat() // convert a 2d array into a flat array
.filter(String) // remove empty elements from the array
.pop(); // get the last element from the array
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message);
}
Update
Here is the full implementation with installable trigger onEdit that sends email as soon as the checkbox (in column L) was checked in:
// global variables
var SS = SpreadsheetApp.getActiveSpreadsheet(); // get the srpreadsheet
var checkbox_col = 12; // column with checkboxes (L in this case)
// the main function
function sendEmail(e) {
try {
var {rowStart, columnStart} = e.range; // get row and column of the cell that was edited
if (columnStart != checkbox_col) return; // do nothing if it was not column with checkboxes
if (e.value != 'TRUE') return; // do nothing if the checkboxs was unchecked
e.range.setValue(false); // else uncheck the chekbox
var sheet = SS.getSheetByName('HLP REQUESTS'); // get the sheet
var emailAddress = sheet.getRange('K' + rowStart).getValue(); // get email addres from current row, column K
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message); // send the message
SS.toast('Email to ' + emailAddress + ' has been sent');
}
catch(e) { SpreadsheetApp.getUi().alert(e) }
}
// additional functions -------------------------------------------------------------------------
// insatll the trigger
function install_onEidt_trigger() {
ScriptApp.newTrigger('sendEmail').forSpreadsheet(SS).onEdit().create();
SS.toast('Trigger was installed');
}
// remove all triggers
function remove_all_triggers() {
ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t));
SS.toast('All triggers were remoded');
}
// custom menu to install and remove triggers
function onOpen() {
SpreadsheetApp.getUi().createMenu('⚙️ Scripts')
.addItem('Install trigger', 'install_onEidt_trigger')
.addItem('Remove all triggers', 'remove_all_triggers')
.addToUi();
}
To make it work you have:
to reload the spreadsheet (or to run the function onEdit() manually) to get the custom menu Scripts
in the custom menu run the item Install trigger
after that it will try to send the message to the address from column K of current row whenever user clicks on checkbox in column L
My test sheet looks like this:
Sending Emails
function SendEmail() {
const ss = SpreadsheetApp.getActive();
const rsh = ss.getSheetByName("HLP REQUESTS");
const emails = rsh.getRange("K1:K" + rsh.getLastRow()).getDisplayValues().flat();
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
emails.forEach(e => {
MailApp.sendEmail(e, subject, message);
});
}
If you wish to attach this to an onEdit you will have to rethink the process because the onEdit trigger fires on every edit to any sheet and most likely you will be require to use an installable onEdit so that you can perform operations that require permission. I'd recommend you play around with the onEdit simple trigger for a while. Look at the event object and see what's available at low overhead cost.
I'm attempting to capture a directly link or the response ID to create a link and forward it into a ticketing queue but every function seems to give me the wrong ID.
function onFormSubmit()
{
//email content creation
var formID = '(copy/pasted from form url)';
var emailBody = "You have received a form submission: ";
var emailAddress = 'TestEmail';
var emailSubject = 'Your form has a new response';
//find the form
var form = FormApp.openById(formID)
var formResponses = form.getResponses();
//find the last response
var lastResponse = formResponses[formResponses.length-1];
var responseID = lastResponse.getID();
//build link
var url = https://docs.google.com/forms/d/ + formID + "/edit#response=" + responseID;
//send email
MailApp.sendEmail(emailAddress, emailSubject, emailBody + url);
}
Hopefully this comes off as coherent on what I'm trying to do. I've attempted to use the
onFormSubmit(e)
responseID = e.getResponses[e.length-1].getID();
but that doesn't work either.
I've found numerous posts on how to do this, but even copy/pasting the test code throws errors of getID being undefined.
If anyone can help figure this out, I would appreciate it!
I have tried to use the search function, but did not find a solution for my problem, or I do not understand enough yet.
I have written a script for google forms, that sends an automatic email to two email addresses, when an user submits the form. I have build in some information that should show in the email subject and puts the input from the forms into the email, with some simple HTML formatting.
My problem is, that the emails always have my Email address as the sender (the account I used for creating the form)
I would like to have the senders email, the one that is submitting the form.
How is that possible?
Here is the code:
function sendFormByEmail(e)
{
// Sent to Email address
var email1 = "123#abc.com";
var email2 = "345#abc.com";
// Variables
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var txt = "";
var subject = "Example text: ";
// Var e = form input as array.
// Loop through the array.
for(var i in headers){
txt += "<b>" + headers[i] + '</b>' + ': '+
e.namedValues[headers[i]].toString() + '<br><br>';
}
// Insert variables from the spreadsheet into the subject.
// Create email subject
subject += "Example text " + e.namedValues[headers[2]].toString();
// Send the email
MailApp.sendEmail(email1, subject, "", {htmlBody:txt});
MailApp.sendEmail(email2, subject, "", {htmlBody:txt});
}
It is not possible to send the mail as the user who submitted the form as the script is running from the user account and the mailapp will send the mail from that account only. you can change the display name according to the user name who submiited the form by the parameter name. Also you can change the email to noreply#domainName.com by adding the parameter noReply in mailApp syntax. However you cannot change it to the user who submitted the form
You can refer this documentation for the above parameters : https://developers.google.com/apps-script/reference/mail/mail-app
Hope this could help
I'm using google apps script to get the responses of a specific form in an specific e-mail,
What I'm trying to do is use a google form to open support tickets, so people need fill some fields like, title, description and e-mail,
And when they submit the form, it will automatically open a ticket, but the e-mail will be always from the owner of the form, and this was a problem because we want that the person who opened the ticket receives email updates, so what I'm trying to do is this:
I put a field in the form asking the persons email, and I'm trying to put that e-mail into the reply-to...
And apparently I'm in the right way to catch that e-mail but the reply-to don't show the email that the persons filled the box, it appears an error: [Ljava.lang.Object;#34dfe075
Does any one can help me?
Here is my script:
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for(var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SendGoogleForm")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function SendGoogleForm(e)
{
try
{
var email = "support#email.com";
var form = e.namedValues;
var subject = form["Title"];
var s = SpreadsheetApp.getActiveSheet();
var columns = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for ( var keys in columns ) {
var key = columns[keys];
if ( e.namedValues[key] && (e.namedValues[key] != "") ) {
message += key + ' :: '+ e.namedValues[key] + "\n\n";
}
}
GmailApp.sendEmail(email, subject, message, {replyTo: form["E-mail"], from: "support#email.com"});
} catch (e) {
Logger.log(e.toString());
}
}
And here is the output of this:
from: support#email.com
reply-to: [Ljava.lang.Object;#34dfe075
to: support#email.com
date: Fri, Oct 17, 2014 at 10:55 AM
subject: New Test
The reply to, is broken :(
The values returned in the e.namedValues property are arrays, so you must access them as such.
Modify your sendEmail line as follows:
GmailApp.sendEmail(email, subject, message, {replyTo: form["E-mail"][0], from: "support#email.com"});
Note the [0] array index on the form["E-Mail"] field, indicating you want the first value in that array, which will be the email address entered.
See the example next to "e.namedValues" here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
I'm trying to update this script to allow me to update the "Sender's" or "Reply To" email address. I'm unsure how to do this as I'm using the script listed here - http://www.labnol.org/?p=20884
I've emailed the developer of this script but have yet to receive a response. Any advice on adding a field to overwrite the default "Reply To" or sender email address?
Thanks for your help!
/* Send Google Form by Email v2.0 */
/* For customization, contact the developer at amit#labnol.org */
/* Tutorial: http://www.labnol.org/?p=20884 */
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
{
// You may replace this with another email address
var email = "CLIENT EMAIL ADDRESS";
// Optional but change the following variable
// to have a custom subject for Google Form email notifications
var subject = "Form Application 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());
}
}
Replace
MailApp.sendEmail(email, subject, message);
with
GmailApp.sendEmail(email, subject, message, {replyTo: "abc#example.com", from: "xyz#example.com"});
The from address has to be an alias though.