My company has a google form that we use to submit requests for data pulls. I created a script that auto emails form responses to myself, as well as a copy to the submitter. The script is:
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 = "My Email Goes here"
var Owner = e.namedValues["Owner:"].toString();
cc = email + "," + Owner
Adv = e.namedValues["Advertiser Name:"].toString();
IO = e.namedValues["IO Name:"].toString();
Tog = "Pixel Request " + Adv + " " + IO;
// Optional but change the following variable
// to have a custom subject for Google Form email notifications
var subject = Tog;
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(cc, subject, message);
} catch (e) {
Logger.log(e.toString());
}
}
The script sends the emails without a problem. However, while the email sent to myself shows up in my sent mail, no copy is delivered to my inbox and it is marked as read; this is a problem because then I do not know that requests have been submitted which was the point of this creation. This seems anomalous as normally emails to yourself will typically show up in the inbox as unread. Does anyone know a way I might be able to fix this?
This is not an issue with the Google Script. This is probably how Gmail handles email where the sender and recipient is you.
Related
I've been writing a client (Chrome browser) App that integrates with GMail via the REST API. My app is written in Javascript/Angular and most of the GMail integration works fine. It can fetch from GMail - emails, profiles, labels, etc.
I'm not able to send emails I create. However, the emails I try to send do appear in the GMail sent list and, if I modify the email by adding the 'INBOX' label, they also appear in the GMail inbox. But none of the emails make it to their destination. I've been testing with several email accounts - Hotmail, Yahoo and another GMail account. Emails are never delivered to their destinations - I've checked the inboxes, spam, etc.
My code is below ... Function 'initializeGMailInterface' is run first (via the User Interface) to authorize and then the 'sendEmail' function (also via the User Interface). The code seems to track with examples I've seen and the documentation Google provides for their REST API. Authentication seems to work OK - and as I mentioned, I'm able to fetch emails, etc.
How do I get the emails to their destination?
var CLIENT_ID = '853643010367revnu8a5t7klsvsc5us50bgml5s99s4d.apps.googleusercontent.com';
var SCOPES = ['https://mail.google.com/', 'https://www.googleapis.com/auth/gmail.send', 'https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.labels'];
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
loadGmailApi();
}
}
$scope.initializeGMailInterface = function() {
gapi.auth.authorize({
client_id: CLIENT_ID,
scope: SCOPES,
immediate: true
}, handleAuthResult);
};
function loadGmailApi() {
gapi.client.load('gmail', 'v1', function() {
console.log("Loaded GMail API");
});
}
$scope.sendEmail = function() {
var content = 'HELLO';
// I have an email account on GMail. Lets call it 'theSenderEmail#gmail.com'
var sender = 'theSenderEmail#gmail.com';
// And an email account on Hotmail. Lets call it 'theReceiverEmail#gmail.com'\
// Note: I tried several 'receiver' email accounts, including one on GMail. None received the email.
var receiver = 'theReceiverEmail#hotmail.com';
var to = 'To: ' +receiver;
var from = 'From: ' +sender;
var subject = 'Subject: ' +'HELLO TEST';
var contentType = 'Content-Type: text/plain; charset=utf-8';
var mime = 'MIME-Version: 1.0';
var message = "";
message += to +"\r\n";
message += from +"\r\n";
message += subject +"\r\n";
message += contentType +"\r\n";
message += mime +"\r\n";
message += "\r\n" + content;
sendMessage(message, receiver, sender);
};
function sendMessage(message, receiver, sender) {
var headers = getClientRequestHeaders();
var path = "gmail/v1/users/me/messages?key=" + CLIENT_ID;
var base64EncodedEmail = btoa(message).replace(/\+/g, '-').replace(/\//g, '_');
gapi.client.request({
path: path,
method: "POST",
headers: headers,
body: {
'raw': base64EncodedEmail
}
}).then(function (response) {
});
}
var t = null;
function getClientRequestHeaders() {
if(!t) t = gapi.auth.getToken();
gapi.auth.setToken({token: t['access_token']});
var a = "Bearer " + t["access_token"];
return {
"Authorization": a,
"X-JavaScript-User-Agent": "Google APIs Explorer"
};
}
Your code is doing an insert(). Do a send() instead:
var path = "gmail/v1/users/me/messages/send?key=" + CLIENT_ID;
The 'emailJS' is a good solution for sending email from Javascript.
EmailJS helps to send emails using client-side technologies only. No server is required.
Additionally, you can easily add attachments, require CAPTCHA validation, switch
between the email services without making code changes, review the history of
the email request, and more.
More Info
I have made a google form that saves data in a spreadsheet, I am writing the code for such spreadsheet so it sends me an email with some data from it, however I am struggling to get one of the values. Column 4 (D) gets the email address from the sender, so I wanna recover that value to put it as a "replyTo" variable and be able to directly reply to whoever is enquiring.
This is my code so far:
function Initialize() {
try {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers)
ScriptApp.deleteTrigger(triggers[i]);
ScriptApp.newTrigger("EmailGoogleFormData")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit().create();
} catch (error) {
throw new Error("Please add this code in the Google Spreadsheet");
}
}
function EmailGoogleFormData(e) {
try {
if (MailApp.getRemainingDailyQuota() > 0) {
// You may replace this with another email address
var email = "nico.pinera#filmmusiclive.com";
/*********** Sender email address || I HAVE PROBLEMS HERE ***********/
var replyTo, senderMail,ss,r_max;
ss = SpreadsheetApp.getActiveSheet();
//r_max = ss.getmaxRows();
// Returns the active cell
var range = ss.getActiveRange();
senderMail = range.getValues()[3];
// Enter your subject for Google Form email notifications
var subject = "Parte de NNTT recibido"
var key, entry,
message = "<b>Hola pepito</b><br/>aa</br><br><br><br><br>",
ss = SpreadsheetApp.getActiveSheet(),
cols = ss.getRange(1, 1, 1, ss.getLastColumn()).getValues()[0];
// Iterate through the Form Fields
for (var keys in cols) {
key = cols[keys];
entry = e.namedValues[key] ? e.namedValues[key].toString() : "";
// Only include form fields that are not blank
if ((entry !== "Sí") && (entry !== "") && (entry !== ",") && (entry.replace(/,/g, "") !== "Sí"))
message += '<img src="" /><br/><br/>' + ' <b><u> ' + key + '</u></b>' + ' => ' + entry ;
}
MailApp.sendEmail(email, replyTo, subject, message);
}
} catch (error) {
Logger.log(error.toString());
}
}
Does anyone have any idea of how can I get the active value from that cell? which would be whatever row in column D.
Also, I did do it by finding the int of maxRows() and then finding the value of the cell of maxRows() and column D, however If I manually edit the spreadsheet (say I manually add a value in the last row), new form requests would be stored above that one and shifting it down. (If I edit row 12 and a new request comes in, my row moves down to 13 and the new one is stored in 12 and so on and so forth).
Short answer
If the required data for the email is included in the form response, instead of using a spreadsheet bounded script, use a form bounded script.
Explanation
Google Forms also could have bounded scripts. Those scripts could be triggered on form submission and the form submission responses are included in the event object as a Form Response object. See Google Form Events and Form Response.
Benefits
To have the responses data in one place, the form file, instead of two, the form file and a spreadsheet.
the responses are in a response object. There is no need to call the value from a cell and this could save a several lines of code and calls to the Google Apps Script services
the response object include the edit response URL that is not added to the spreadsheet by default.
Brief code example
Simplified version of the code posted at Sending Confirmation Emails from Google Apps Forms by Les Bell and adapted to add the email address submitted as response to the reply-to parameter
function sendConfirmationEmail(e) {
// e is a Form Event object
// Edit this to set the subject line for the sent email
var subject = "Registration Successful";
// This will show up as the sender's name
var sendername = "Your Name Goes Here";
// This is the body of the registration confirmation message
var message = "Thank you for registering.<br>We will be in
touch.<br><br>";
// response is a FormResponse
var response = e.response;
var textbody, sendTo, bcc, replyTo;
// Get the script owner's email address, in order to bcc: them
bcc = Session.getActiveUser().getEmail();
// Now loop around, getting the item responses and writing them
// into the email message
var itemResponses = response.getItemResponses();
for (var i = 0; i < itemResponses.length; i++) {
var itemResponse = itemResponses[i];
// If this field is the email address, then use it to fill in
// the sendTo variable
// Check that your form item is named "Email Address" or edit to match
if (itemResponse.getItem().getTitle() == "Email Address") {
sendTo = itemResponse.getResponse();
replyTo = sendTo;
}
}
GmailApp.sendEmail(sendTo, subject, message, {
bcc: bcc,
name: sendername,
htmlBody: message,
replyTo: replyTo
});
}
Complete Code
The below code was taken from Sending Confirmation Emails from Google Apps Forms by Les Bell. The URLs included as comments were removed and some breaklines were added to avoid the appearance of the horizontal scroll bar.
Its purpose is to send the submitted responses and the edit response URL to the email address captured in the form submission.
function setup() {
/* First, delete all previous triggers */
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
/* Then add a trigger to send an email on form submit */
ScriptApp.newTrigger("sendConfirmationEmail")
.forForm(FormApp.getActiveForm())
.onFormSubmit()
.create();
}
function sendConfirmationEmail(e) {
// e is a Form Event object
// Edit this to set the subject line for the sent email
var subject = "Registration Successful";
// This will show up as the sender's name
var sendername = "Your Name Goes Here";
// This is the body of the registration confirmation message
var message = "Thank you for registering.<br>We will be in touch.
<br><br>";
message += "Your form responses were:<br><br>";
// response is a FormResponse
var response = e.response;
var textbody, sendTo, bcc;
// Get the script owner's email address, in order to bcc: them
bcc = Session.getActiveUser().getEmail();
// Now loop around, getting the item responses and writing them
// into the email message
var itemResponses = response.getItemResponses();
for (var i = 0; i < itemResponses.length; i++) {
var itemResponse = itemResponses[i];
message += itemResponse.getItem().getTitle() +": "
+ itemResponse.getResponse() + "<br>";
// If this field is the email address, then use it to fill in
// the sendTo variable
// Check that your form item is named "Email Address" or edit
// to match
if (itemResponse.getItem().getTitle() == "Email Address") {
sendTo = itemResponse.getResponse();
}
}
message += "<br>If you wish to edit your response, please click on
<a href=\""
+ response.getEditResponseUrl()
+ "\">this link</a>.";
message += "<br><br>";
textbody = message.replace("<br>", "\n");
GmailApp.sendEmail(sendTo, subject, textbody,
{bcc: bcc, name: sendername, htmlBody: message});
}
Using Slack, and trying to set up an Outgoing Webhook to send an email when a user types in a certain keyword. Slack sends a POST in the following format:
token=XXXXXXXXXXXXXXXXXX
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
timestamp=1355517523.000005
user_id=U2147483697
user_name=Steve
text=atsk: ticket#; ticket details
trigger_word=atsk:
It sends this POST to a URL that is set up with this Google script:
function autoMail(sendmail) {
var params = sendmail.parameters;
if (params.token == "XXXXXXXXXXXXXXXXXX") {
var textRaw = String(params.text).replace(/^\s*atsk\s*:*\s*/gi,'');
var text = textRaw.split(/\s*;\s*/g);
var email = "example#gmail.com";
var subject = text[0];
var message = text + "Ticket created by Autoslack Bot";
MailApp.sendEmail(email, subject, message);
} else {
return;
}
}
Which is published as a Web App and set to run as 'Anyone, even anonymous' and been granted permission to use my Google Email.
So if someone types 'atsk: T12345678; User has an issue.' it should send an email to 'example#gmail.com' with the subject 'T12345678' and the message 'T12345678; User has an issue. Ticket created by Autoslack Bot'
I thought this was set up correctly, but I cannot get an email to send to the specified address. Can someone help, please?
I would suggest to create a test function to check the Apps script part on its own like this :
function testAutoMail() {
var parameters={};
parameters['text']='atsk: T12345678; User has an issue.';
parameters['token']="XXXXXXXXXXXXXXXXXX";
var arg = {};
arg['parameters']=parameters;
autoMail(arg);
}
function autoMail(sendmail) {
var params = sendmail.parameters;
if (params.token == "XXXXXXXXXXXXXXXXXX") {
var textRaw = String(params.text).replace(/^\s*atsk\s*:*\s*/gi,'');
var text = textRaw.split(/\s*;\s*/g);
var email = "example#gmail.com";
var subject = text[0];
var message = text + "Ticket created by Autoslack Bot";
Logger.log('MailApp.sendEmail('+email+', '+subject+', '+message+')');
} else {
return;
}
}
And look at the Logger to see if it works.
I want to get email once the form is submitted with only the filled in responses but not the blank or empty fields.
I have did some research and found the below script which triggers email immediately to the email address present in the form. Also the email contains all the fields including the empty fields.
Please help me achieve a script which fulfills my requirement.
function setup() {
/* First, delete all previous triggers */
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
/* Then add a trigger to send an email on form submit */
ScriptApp.newTrigger("sendConfirmationEmail")
.forForm(FormApp.getActiveForm())
.onFormSubmit()
.create();
}
function sendConfirmationEmail(e) {
// e is a Form Event object - see https://developers.google.com/apps-script/guides/triggers/events#google_forms_events
// Edit this to set the subject line for the sent email
var subject = "Registration Successful";
// This will show up as the sender's name
var sendername = "Your Name Goes Here";
// This is the body of the registration confirmation message
var message = "Thank you for registering.<br>We will be in touch.<br><br>";
message += "Your form responses were:<br><br>";
// response is a FormResponse - see https://developers.google.com/apps-script/reference/forms/form-response
var response = e.response;
var textbody, sendTo, bcc;
// Get the script owner's email address, in order to bcc: them
bcc = Session.getActiveUser().getEmail();
// Now loop around, getting the item responses and writing them into the email message
var itemResponses = response.getItemResponses();
for (var i = 0; i < itemResponses.length; i++) {
var itemResponse = itemResponses[i];
message += itemResponse.getItem().getTitle() +": " + itemResponse.getResponse() + "<br>";
// If this field is the email address, then use it to fill in the sendTo variable
// Check that your form item is named "Email Address" or edit to match
if (itemResponse.getItem().getTitle() == "Email Address") {
sendTo = itemResponse.getResponse();
}
}
message += "<br>If you wish to edit your response, please click on this link.";
message += "<br><br>";
textbody = message.replace("<br>", "\n");
GmailApp.sendEmail(sendTo, subject, textbody,
{bcc: bcc, name: sendername, htmlBody: message});
I have found the solution to my question. I am posting it below for knowledge sharing. Thank you.
Paste the below script in the responses spreadsheet's script editor. First run the initialise function to start the script, and later whenever the form is submitted a email will be triggered with only the filled out fields form the form.
function Initialize() {
try {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers)
ScriptApp.deleteTrigger(triggers[i]);
ScriptApp.newTrigger("EmailGoogleFormData")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit().create();
} catch (error) {
throw new Error("Please add this code in the Google Spreadsheet");
}
}
function EmailGoogleFormData(e) {
if (!e) {
throw new Error("Please go the Run menu and choose Initialize");
}
try {
if (MailApp.getRemainingDailyQuota() > 0) {
// You may replace this with another email address
var email = "email address";
// Enter your subject for Google Form email notifications
var subject = "Form Submitted";
var key, entry,
message = "",
ss = SpreadsheetApp.getActiveSheet(),
cols = ss.getRange(1, 2, 1, ss.getLastColumn()).getValues()[0];
// Iterate through the Form Fields
for (var keys in cols) {
key = cols[keys];
entry = e.namedValues[key] ? e.namedValues[key].toString() : "";
// Only include form fields that are not blank
if ((entry !== "") && (entry.replace(/,/g, "") !== ""))
message += key + ' :: ' + entry + "\n\n";
}
MailApp.sendEmail(email, subject, message);
}
} catch (error) {
Logger.log(error.toString());
}
}
Project key: MyvPlY2KvwGODjsi4szfo389owhmw9jII
I am trying to run a script that sends the contents of my form by email each time the form is submitted. I was following the instructions from this link below exactly until I started getting errors and I received advice to change my script to open spreadsheets by id:
http://www.snipe.net/2013/04/email-contents-google-form/
When I complete the form, it is supposed to email the contents to my email.
The problem I am now having is that the function which goes through the form values doesn't work. It's returning the error
TypeError: Cannot read property "namedValues" from undefined. (line 15, file "Code")"
in regards to the piece of code below:
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
I am not too familiar with Google Apps Scripts so I'm not sure how to work around this issue either. Is there anything you recommend? I have included the entire script below.
function sendFormByEmail(e)
{
// Remember to replace this email address with your own email address
var email = "sample#email.com";
var s = SpreadsheetApp.openById("1hOqnK0IVa2WT6-c-MY0jyGGSpIJIV2yzTXdQYX4UQQA").getSheets()[0];
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var subject = "New User Form";
// The variable e holds all the form values in an array.
// Loop through the array and append values to the body.
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
// Insert variables from the spreadsheet into the subject.
// In this case, I wanted the new hire's name and start date as part of the
// email subject. These are the 3rd and 16th columns in my form.
// This creates an email subject like "New Hire: Jane Doe - starts 4/23/2013"
subject += e.namedValues[headers[2]].toString() + " - starts " + e.namedValues[headers[15]].toString();
// Send the email
MailApp.sendEmail(email, subject, message);
}
The function appears to be undefined as 'e' is not received as part of the function context. You'll need to set a trigger for the submission of the form, and send the information to the function. You can use the following code:
/* 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());
}
}
I have the same error and it took me some time to figure out how to solve it.
The problem is that you are writing your code in the form, and you should do it in your spreadsheet.
When I created the function inside the form and registered the event, it was called but the parameter didn't have the same structure (and didn't have the field namedValues, so the error "Cannot read property "namedValues" from undefined"). A better way to check this is to log the object as a JSON string:
Logger.log("e: " + JSON.stringify(e));
So, the steps I have made to correct this issue:
Create a spreadsheet
Create the form through the spreadsheet (inside the spreadsheet select Tools->Create a form), and create your form
Go back to your spreadsheet, and create the script (Tools->Script Editor)
Write your function
Register the function (Edit->Current Project's Triggers): function sendFormByEmail, Event: From Spreadsheet -> On form submit
Hope this helps
There is an error in this line of code:
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
it's this part:
e.namedValues[headers[i]].toString()
I'm just guessing that you want:
e.namedValues + [headers[i]].toString()
You're missing a plus sign if you want to concatenate the values.