// 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; }