// This is a copy of the Google Script used for handling form submissions.
var TO_ADDRESS = "foo@bar.com";
function isMeta(field) {
const f = String(field);
if (f === 'formDataNameOrder') return true;
if (f === 'formGoogleSheetName') return true;
if (f === 'formGoogleSendEmail') return true;
if (f === 'honeypot') return true;
if (f === 'human') return true;
if (f === 'form-name') return true;
if (f === 'email') return true;
return false;
}
// spit out all the keys/values from the form in HTML for email
// uses an array of keys if provided or the object to determine field order
function formatMailBody(obj, order) {
var result = "";
if (!order) {
order = Object.keys(obj);
}
// loop over all keys in the ordered form data
for (var idx in order) {
var key = order[idx];
var val = obj[key];
if (isMeta(key)) {
continue;
}
result += "
" + sanitizeInput(key) + "
" + sanitizeInput(val) + "
";
// for every key, concatenate an ``/`` pairing of the key name and its value,
// and append it to the `result` string created at the start.
}
return result; // `result` will be one long string to put in the email body
}
// sanitize content from the user - trust no one
// ref: https://developers.google.com/apps-script/reference/html/html-output#appendUntrusted(String)
function sanitizeInput(rawInput) {
var placeholder = HtmlService.createHtmlOutput(" ");
placeholder.appendUntrusted(rawInput);
return placeholder.getContent();
}
function doPost(e) {
try {
Logger.log(e); // the Google Script version of console.log see: Class Logger
var mailData = e.parameters;
var bah = 3;
if (typeof String(mailData.email) !== "undefined" && String(mailData.email).length > 0) {
// If honeypot is triggered we just ignore this submission.
throw new Error("Honeypot field triggered, treating message is spam.");
}
if (typeof String(mailData.human) === "undefined" || String(mailData.human) !== "human") {
// If "human" is not found in "human" field we just ignore this submission.
throw new Error("Bot check failed, there was a field where you were supposed to type: human.");
}
record_data(e);
// names and order of form elements (if set)
var orderParameter = e.parameters.formDataNameOrder;
var dataOrder;
if (orderParameter) {
dataOrder = JSON.parse(orderParameter);
}
var sendEmailTo = TO_ADDRESS;
var replyTo = (typeof String(mailData.emailReal) !== "undefined" ? String(mailData.emailReal) : "no-reply@baobab.fi")
MailApp.sendEmail({
to: String(sendEmailTo),
subject: "attejuvonen.fi visitor submitted contact form",
replyTo: String(replyTo),
htmlBody: formatMailBody(mailData, dataOrder)
});
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
/**
* record_data inserts the data received from the html form submission
* e is the data received from the POST
*/
function record_data(e) {
var lock = LockService.getDocumentLock();
lock.waitLock(30000); // hold off up to 30 sec to avoid concurrent writing
try {
Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
// select the 'responses' sheet by default
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = e.parameters.formGoogleSheetName || "responses";
var sheet = doc.getSheetByName(sheetName);
var oldHeader = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var newHeader = oldHeader.slice();
var fieldsFromForm = getDataColumns(e.parameters);
var row = [new Date()]; // first element in the row should always be a timestamp
// loop through the header columns
for (var i = 1; i < oldHeader.length; i++) { // start at 1 to avoid Timestamp column
var field = oldHeader[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
// mark as stored by removing from form fields
var formIndex = fieldsFromForm.indexOf(field);
if (formIndex > -1) {
fieldsFromForm.splice(formIndex, 1);
}
}
// set any new fields in our form
for (var i = 0; i < fieldsFromForm.length; i++) {
var field = fieldsFromForm[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
newHeader.push(field);
}
// more efficient to set values as [][] array than individually
var nextRow = sheet.getLastRow() + 1; // get next row
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// update header row with any new data
if (newHeader.length > oldHeader.length) {
sheet.getRange(1, 1, 1, newHeader.length).setValues([newHeader]);
}
}
catch(error) {
Logger.log(error);
}
finally {
lock.releaseLock();
return;
}
}
function getDataColumns(data) {
return Object.keys(data).filter(function(column) {
return !(column === 'formDataNameOrder' || column === 'formGoogleSheetName' || column === 'formGoogleSendEmail' || column === 'Honeypot' || column == 'Form-name' || column == 'Email' || column == 'human');
});
}
function getFieldFromData(field, data) {
var values = data[field] || '';
var output = values.join ? values.join(', ') : values;
return output;
}