Syntax issue involving a ".replace" function - javascript

So I have a Google sheet that collects registration data from customers. Included in the data collected is a student's name, the session the student elected to attend and a credit card number. Once a submission has been made, I get a notification. Upon notification, I go to my Google sheet and charge the credit card the appropriate amount.
Once the credit card has been charged, I then want to generate a confirmation email to the customer that includes the student's name, the session the student registered to attend and the amount charged to the credit card. My code seems to work fine except when it comes to replacing curly bracket placeholders in my "template text" (i.e., {Name},{sessions} and {ChargeAmount} with the actual values which I've defined as variables.
Note: When I just replace {StudentName} with text like "Joe" it works. However, {Sessions} does not get replaced and neither does {ChargeAmount}. I think this is a syntax error.
Here's what I really want to happen but can't get to work:
var emailText = templateText.replace("{Name}",studentName);templateText.replace("{Sessions}",sessionName);templateText.replace("{ChargeAmount}",ChgAmt);
function SendEmail() {
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("B2");
var studentRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("C2");
var studentName = studentRange.getValues();
var sessionRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("D2");
var sessionName = sessionRange.getValues();
var emailAddress = emailRange.getValues();
var ChgAmt = Browser.inputBox("Charge Amount");
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1,1).getValue();
// NOTE! What I really want to do is replace {Name} with the var "studentName"... not the text "Joe", {Sessions} with the var "sessionName" and {ChargeAmount} with the var "ChgAmt". I can't this to work either! STRUGGLING!!!
var emailText = templateText.replace("{StudentName}","Joe");templateText.replace("{Sessions}","May - Session#1");templateText.replace("{ChargeAmount}","$500");
// Send Alert Email.
var subject = 'Junior Golf Clinic Registration Receipt';
var message = emailText;
MailApp.sendEmail(emailAddress, subject, message);
}
Here's the result of my existing code which does not properly pull in the values I need.
useremail#gmail.com
9:18 AM (37 minutes ago)
to me
This is the email body.
This is the amount charged to credit card {ChargeAmount}. [Not right. This should be the actual value represented by the var "ChgAmt"]
This is the student's name: Joe [this seems to work when I replace the placeholder {Name} with text like "Joe" but not when I try to replace the placeholder {Name} with the var "studentName"]
These are the sessions the student is scheduled to attend: {Sessions}
[Not right. This should be the actual sessions represented by the var "sessionName"]
Here's more information about the clinics themselves.

This line is incorrect, you're never actually storing your other replace statements.
var emailText = templateText.replace("{StudentName}","Joe");templateText.replace("{Sessions}","May - Session#1");templateText.replace("{ChargeAmount}","$500");
It should be:
var emailText = templateText.replace("{StudentName}","Joe").replace("{Sessions}","May - Session#1").replace("{ChargeAmount}","$500");

As jmcgriz notes, the problem is with the separate calls to .replace. Chaining them fixes your issue.
Here is some dummy code showing what that might look like:
function SendEmail() {
// fetch these values as you need
var studentName = 'Joe'
var sessionName = "May - Session#1";
var emailAddress = 'joe#joe.com'
var chargeAmt = "$500";
// This is what needed to change
var emailText = templateText
.replace("{StudentName}", studentName)
.replace("{Sessions}", sessionName)
.replace("{ChargeAmount}", chargeAmt);
var subject = 'Junior Golf Clinic Registration Receipt';
var message = emailText;
MailApp.sendEmail(emailAddress, subject, message);
}
SendEmail()
<script>
// Mocking MailApp for testing
const MailApp = {
sendEmail: (addr, subj, mess) =>
console.log(`Sending "${addr}" email "${subj}"\n\n${mess}`)
}
const templateText = `
This is the email body.
This is the amount charged to credit card {ChargeAmount}.
This is the student's name: {StudentName}
These are the sessions the student is scheduled to attend: {Sessions}
Here's more information about the clinics themselves.`
</script>

Related

MailApp.sendEmail sending email to my inbox even my even not set together to get the email

I have an email script that will send out email to all emails that are in the list of a google sheet. But then, when I run the script, it is also sent to my Inbox instead of only to register into my Sent folder. Before this no issue (after being using the same script for a long time, 1+ year), it just happened a few months back.
I've found similar issue from this post but couldn't get the suggestions work, example:
To replace Mailapp.sendEmail with Gmailapp.sendEmail
Checked if I have any wrong filter in my email
Attached the script as below:
function arrayUnique(arr) {
var tmp = [];
// filter out duplicates
return arr.filter(function(item, index){
var stringItem = item.toString(); // convert row arrays to strings for comparison
tmp.push(stringItem); // push string items into temporary arrays
return tmp.indexOf(stringItem) >= index; // only return the first occurrence of the strings
})}
function sendEmail() {
var sheet = SpreadsheetApp.getActive().getSheetByName("pending list")
var sub = "Error Fix Required"
var data = sheet.getRange(3,1, sheet.getLastRow(), 5).getDisplayValues().filter(function (row){
var date = sheet.getRange(1,2).getDisplayValues()
return row[3] == date
})
var filterunique = arrayUnique(data)
var json = {}
filterunique.forEach(function (item){
if(item[2] || item[2].length > 0){
if(!json[item[2]]){
json[item[2]] = []
}
json[item[2]].push(item[0])
}
})
Object.keys(json).forEach(function(to){
var email = "{{user}}#shopee.com"
email = email.replace(/{{user}}/gi,to)
var sku = "<br><ul><li>" + json[to].join("</li><li>") + "</li></ul>"
var body = "Hi " + to +", <br><br>The following require your kind attention:" + sku + "Please go to this <a href='https://docs.google.com/spreadsheets/d/1nMKeW//'>link</a> to rectify your submissions by today 4pm.<br><br> Thanks."
MailApp.sendEmail({
to: email,
subject: sub,
htmlBody: body
});
})
}
Also attached what I received in my Inbox:
Change this:
MailApp.sendEmail({to: email,subject: sub, htmlBody: body});
to this:
GmailApp.sendEmail(emai,sub,'',{htmlBody:body});

MailApp not sending with large number of recipients

My code takes an input of emails that looks like this:
email1#gmail.com, email2#gmail.com, email3#gmail.com ...
and tries to send them an email using the following code.
function sendEmail(form) {
var ss = SpreadsheetApp.getActive();
var body = form.body;
var bcc = form.bccfield;
var cc = form.ccfield;
var to = form.tofield;
var subject = form.subject;
var eHandle = ss.getSheetByName("Email Handling");
var sig = eHandle.getRange(10, 2).getValue();
var img = eHandle.getRange(11, 2).getValue();
var sigImage = '<img src ="' + img + '" >';
MailApp.sendEmail({
to: to,
cc: cc,
bcc: bcc,
subject: subject,
htmlBody: body.replace(/\n/g, '<br>') + sig + sigImage});
}
It seemed to always be working but now I'm trying to send to a class list of parents (about 55 at a time) and it just doesn't send anything (the code doesn't even finish). I am GSuite for Education so I should have a limit of over 1,000 recipients per day.
I'm pretty sure the only difference which now causes a problem is the number of recipients.
You are not allowed to sent an email to more than 50 recipients at a time.
Number of recipients per email is part of Quotas for Google Services.
You are only allowed to sent an email with a maximum number of 50 recipients.
An obvious workaround would be to split the recipients into two or more (depending upon the number of recipients) different emails so this hard limitation won't be violated.

Replacing commas with \n, data exports as "undefined", "Cannot find function map in object"

GOAL: Player submits Google Form indicating which games they would like to sign up for (using checkboxes - data is collected in Column C, labeled "Game"); email is automatically sent confirming their registration (including a list of the games they signed up for) and additional static information / FAQs; Google Sheet indicates that the email was successfully sent. OPTIONAL: Each game that appears in the email confirmation has a hyperlink to a corresponding game page.
Issue #1: Attempt to use .map(function) results in
TypeError: "Cannot find function map in object".
If I remove the .map and just make the var gamesHtml = games, then the script runs okay, but returns an all lowercase, comma delimited list. e.g.
twist workshop game - oct. 14th 8-10pm est, twist three act - oct. 18th 1-5pm est, twist two act - oct. 23rd 7-10pm est
If I try to remove .toLowerCase() from both instances in the script then I get an "undefined" error.
Issue #2 (aka Failed attempt at a work-around): I have a step in the script that replaces the commas with /n from Column C and puts a copy in Column L (labeled "Breakdown"), pulled as var emailList. If I try to call this in function createEmailBody(name, games, emailList) / "emailBody = emailBody.replace(/{{GAMES}}/g, gamesHtml);" then I get an undefined error in the resulting email.
General Question: If I try to do var emailList = responses.Breakdown[0] I receive TypeError: Cannot read property "0" from undefined. at onFormSubmit(Code:45). Why is that? What is the purpose of the [0]? (Having trouble "Googling" that question.) Is it because I have line breaks in the cell that it's pulling from?
FWIW, I am not running Chrome V8.
Google Sheets Layout
var EMAIL_TEMPLATE_DOC_URL = 'https://docs.google.com/document/d/14aQ-1ekAH_rbcF7S5U4lWRsG_uQQcXvlpQoEXsW3z5k/edit?usp=sharing';
var EMAIL_SUBJECT = 'TWIST Confirmation';
var gameUrls = {
"TWIST Three Act - Oct. 4th 1-5pm EST": 'http://www.twistvirtual.com',
"TWIST Workshop Game TBD - Oct. 7th 8-10pm EST": 'http://www.twistvirtual.com',
"TWIST Three Act - Oct. 10th 12-4pm EST": 'http://www.twistvirtual.com',
"TWIST Workshop Game TBD - Oct. 14th 8-10pm EST": 'http://www.twistvirtual.com',
"TWIST Three Act - Oct. 18th 1-5pm EST": 'http://www.twistvirtual.com',
"TWIST Two Act - Oct. 23rd 7-10pm EST": 'http://www.twistvirtual.com',
"TWIST Workshop Game TBD - Oct. 25th 2-5pm EST": 'http://www.twistvirtual.com',
"TWIST Three Act - Nov. 1st 1-5pm EST": 'http://www.twistvirtual.com',
"I can't make these games but want to play in the future!" : 'http://www.twistvirtual.com',
};
function onFormSubmit(e) {
Logger.log(e.namedValues);
var ss = SpreadsheetApp.getActiveSpreadsheet();//gets the spreadsheet you attached the script to
var sheet = ss.getActiveSheet();//gets whatever sheet is in the front
var lastRow = ss.getLastRow();//gets the last row of entered data
var yourColumn = "L";//set your column
var yourFunction = '=substitute(C'+ lastRow + ',", ",char(10))';//whatever function or formula or data you want, just don't forget to use lastRow do do the row number
ss.getRange(yourColumn+lastRow).setValue(yourFunction);
var pasted = ss.getRange(yourColumn+lastRow).getValue();
var listed = pasted.toString().replace(/,/g,'\n');
ss.getRange("L"+lastRow).setValue(listed);
Logger.log(listed);
Logger.log('Attempting to send email')
// 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 responses = e.namedValues;
var timestamp = responses.Timestamp[0];
var email = responses.Email[0].trim();
var name = responses.Name[0].trim();
var gamesString = responses.Game[0].toLowerCase();
var emailList = responses.Breakdown;
// Parse games of interest into a list (since there are multiple items
// that are saved in the row as blob of text).
var games = Object.keys(gameUrls).filter(function(game) {
// indexOf searches for the game in gamesString and returns a non-negative
// index if the game is found, or it will return -1 if it's not found.
return gamesString.indexOf(game.toLowerCase()) != -1;
});
// If there is at least one game selected, send an email to the recipient.
var status = '';
if (games.length > 0) {
MailApp.sendEmail({
to: email,
subject: EMAIL_SUBJECT,
htmlBody: createEmailBody(name, gamesString),
});
status = 'Sent '+ new Date();
}
else {
status = 'Error';
}
// Append the status on the spreadsheet to the responses' row.
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var column = "G";
ss.getRange(column+lastRow).setValue(status);
Logger.log("status=" + status + "; responses=" + JSON.stringify(responses));
}
/**
* Creates email body and includes the links based on game.
*
* #param {string} recipient - The recipient's email address.
* #param {string[]} games - List of games to include in the email body.
* #return {string} - The email body as an HTML string.
*/
/** ORIGINAL var gamesHtml which returns TypeError: "Cannot find function map in object":
function createEmailBody(name, games) {
var gamesHtml = games.map(function(game) {
var url = gameUrls[game];
return '<li>' + game + '</li>';
}).join('');
gamesHtml = '<ul>' + gamesHtml + '</ul>';
*/
function createEmailBody(name, games) {
var gamesHtml = games
// 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);
emailBody = emailBody.replace(/{{GAMES}}/g, gamesHtml);
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();
}

Extracting Email Address & Name From Forwarded Emails

I'm trying to use Google Script to extract email address and name from forwarded emails that I've filed under a specific label.
The emails look like this:
From: Person A
Sent: Sunday, September 22, 2019 8:00 PM
To: Other, Email
Subject: Forwarded Email
BODY
They have all have been forwarded to this specific inbox. Therefore the headers actually include my other email address I forwarded from.
I've sorted over 2000 emails and now for each of the labels I want to extract the name of the sender (Person A) and their email address (person#gmail.com) in a spreadsheet. Preferably, I can have the first and last name in separate cells (e.g. Person | A | email address)
The code I have thus far is below:
function processInboxToSheet() {
// Have to get data separate to avoid google app script limit!
var start = 0;
var label = GmailApp.getUserLabelByName("LABEL");
var threads = label.getThreads();
var sheet = SpreadsheetApp.getActiveSheet();
var result = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
var content = messages[0].getPlainBody();
// implement your own parsing rule inside
if (content) {
var tmp;
tmp = content.match(/From:\n([A-Za-z0-9\s]+)(\r?\n)/);
var name = (tmp && tmp[1]) ? tmp[1].trim() : 'No name';
tmp = content.match(/<\n([A-Za-z0-9#.]+)/);
var email = (tmp && tmp[1]) ? tmp[1].trim() : 'No email';
sheet.appendRow([name, email]);
Utilities.sleep(500);
}
}
};
I only get No name and No email as output so something is not quite working in the code. I would appreciate your help.
You are parsing the plain body, it doesn’t contain to and from. It only contains the message body. The API has methods getTo() and getFrom() that contains what you want to parse. See the API for GmailMessage for more details.

Google Scripts: Pull Google Document Based on User ID / Email

Good Morning Stack!
I was looking for some advice for some expanded functionality on a Google Script that helps me track and process absence requests. The process is as follows:
A user submits their form responses
The form responses are stored on a spreadsheet
A google doc, pre-created, is pulled and the values from the spreadsheet are implanted in the document.
The document is converted to a PDF
That PDF is automatically emailed to me.
However, some work policies have changed and I now need this form to have a signature that is unique to the person filling the form. In the past we simply printed the resulting PDF and had the person sign off on it.
I know I do not have the technicality to add on any sort of Electronic Signature functionality, nor is emailing that PDF to them an option as it doesn't create a fillable PDF (and my users don't really know how to digitally sign items anyways)
So what I was thinking is to create a form unique to each of the 15-20 users of this process and instead of a getFileByID, have the script check the Google Users account / email and pull the file created for them and stored in my drive instead.
As follows is my current, functional, script. How could I make this work?
function onFormSubmit(e) {
var Last_Name = e.values[2];
var First_Name = e.values[3];
var Middle_Initial = e.values[4];
var Work_Location = e.values[5];
var Job_Title = e.values[6];
var Contact_Number = e.values[7];
var Start = e.values[8];
var End = e.values[9];
var Time = e.values[10];
var Reason = e.values[11];
var D = new Date();
var copyId = DriveApp
.getFileById("1sdfjlsdf55asdfnk565enasdfnsnsd2")
.makeCopy("AbsenceRequest" + Last_Name + Start).getId();
var copyDoc = DocumentApp.openById(copyId)
var copyBody = copyDoc.getActiveSection();
copyBody.replaceText('keyLastName', Last_Name);
copyBody.replaceText('keyFirstName', First_Name);
copyBody.replaceText('keyMiddleInitial', Middle_Initial);
copyBody.replaceText('keyWorkLocation', Work_Location);
copyBody.replaceText('keyJobTitle', Job_Title);
copyBody.replaceText('keyContactNumber',Contact_Number);
copyBody.replaceText('keyStart', Start);
copyBody.replaceText('keyEnd', End);
copyBody.replaceText('keyTime', Time);
copyBody.replaceText('keyDate', D);
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var Email = "email#email.org" + "," + "email#email.org";
var Subject = "Absence Request"
var Body = "This is an absence request"
MailApp.sendEmail(Email, Subject, Body, {attachments: pdf});
DriveApp.getFileById(copyId).setTrashed(true);
}

Categories

Resources