getChild of body of gmail email using Goole Apps Scripts (GAS) - javascript

Problem
I have automated emails coming to me with particular client details in them. I have the repetitive task of repling to each email with a template. I am wanting to automate the process utilising Google Apps Scripts.
Where I'm up to
I have worked out how to collect the body of the email I am replying to. I'm trying to get the third paragraph info and store this in a variable.
Here is my code:
function autoReply() {
//Capturing the automated email
var queryInbox = "is:unread from:(example#gmail.com)";
var locatedEmail = GmailApp.search(queryInbox);
for (var i in locatedEmail){
var thread = locatedEmail[i];
var messages = thread.getMessages();
var msgBody = messages[i].getBody();
var clientsEmail = msgBody.getChild('p')[3]; //Attempting to obtain the third paragraph of the body.
if(messages.length === 1) {
var body = "<p> The clients email is: " + clientsEmail + "</p>";
};
var options = { name: "Temp Name",htmlBody: body };
thread.reply(body, options);
thread.markRead();
thread.moveToArchive();
}
};
Note: Img attached for context.

I believe your goal as follows.
When the thread has one message, you want to retrieve the body of email.
You want to retrieve the 3rd paragraph from the message of email.
You want to reply the message including the retrieved 3rd paragraph.
Modification points:
At for (var i in unread){, I thought that you might use locatedEmail.
When you want to reply the message with messages.length === 1, var msgBody = messages[i].getBody(); is required to be modified. Because in your for loop, the index i is used for var thread = locatedEmail[i]; and var msgBody = messages[i].getBody();.
In your case, I think that getPlainBody() instead of getBody() might be suitable.
When above points are reflected to your script, it becomes as follows.
Modified script:
function autoReply() {
var queryInbox = "is:unread from:(example#gmail.com)";
var locatedEmail = GmailApp.search(queryInbox);
locatedEmail.forEach(thread => {
var messages = thread.getMessages();
if (messages.length === 1) {
var msgBody = messages[0].getPlainBody();
var clientsEmail = msgBody.split("\n")[2]; // Here, the 3rd paragraph is retrieved.
var body = "<p> The clients email is: " + clientsEmail + "</p>";
var options = { name: "Temp Name",htmlBody: body };
thread.reply(body, options);
thread.markRead();
thread.moveToArchive();
}
});
}
Reference:
getPlainBody()

Related

how to getRange of more than one cell in same row in a script

Im trying to make a script that sends email alert when specific fields reaches certain values. It works fine for one field, but how Do I do it so it sends alert when any of the fields in specific row range reaches that value.
Im using this code:
function CheckSales() {
// Tikrinam laukelio value
var monthSalesRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("reportai").getRange("A15");
var monthSales = monthSalesRange.getValue();
// tikrinam value
if (monthSales < 200){
// pasiimam email adresa
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("B2");
var emailAddress = emailRange.getValue();
// Siuncima email.
var message = 'Mazas likutis: ' + monthSales; // Second column
var subject = 'Mazas Likutis';
MailApp.sendEmail(emailAddress, subject, message);
}
}
I tried using .getRange("A15:E15") but still it send alert only when A15 reaches value less than 200, its not reacting to B15, C15 ect.
You need to iterate the values in A15:E15 with a loop. Try this:
function checkSales() {
const monthSalesRange = SpreadsheetApp.getActive().getRange('reportai!A15:E15');
const emailAddress = SpreadsheetApp.getActive().getRange('Sheet1!B2').getValue();
const subject = 'Mazas Likutis';
let message = 'Mazas likutis: ';
const alerts = [];
monthSalesRange.getValues().flat()
.forEach(sales => {
if (Number(sales) && sales < 200) {
alerts.push(sales);
}
});
if (alerts.length) {
MailApp.sendEmail(emailAddress, subject, message + alerts.join(', '));
}
}
Some of the best resources for learning Google Apps Script include the Beginner's Guide, the New Apps Script Editor guide, the Fundamentals of Apps Script with Google Sheets codelab, the Extending Google Sheets page, javascript.info, Mozilla Developer Network and Apps Script at Stack Overflow.

update spreadsheet in serverside code run from client html javascript not working

I have an html where user requests add and enters data. The javascript in the body of the html calls the server side. I am unable to connect with the sheet either with saved ID or URL in order to add the row.
I cannot update of my spreadsheet despite #Serge insas comment that openById "it means "open for read and write". Am I making a simple mistake or is this impossible. The code initiated from the client side is running in the server.
const ssId = PropertiesService.getScriptProperties().getProperty('ssId');
var sheet = SpreadsheetApp.openById("[ssId]").getSheetByName('Sheet1');
const ssId = PropertiesService.getScriptProperties().getProperty('ssId');
var sheet = SpreadsheetApp.openById("ssId").getSheetByName('Sheet1');
Both get Error: Exception: Unexpected error while getting the method or property openById on object SpreadsheetApp.
const ssUrl = PropertiesService.getScriptProperties().getProperty('ssUrl');
var sheet = SpreadsheetApp.openByUrl("ssUrl").getSheetByName('Sheet1');
Gets error: Exception: Invalid argument: url
ABOVE IS THE IMPORTANT PART
/**
* this code is run from the javascript in the html dialog
*/
function addMbrCode(myAddForm) {
// removed logging
console.log("Beginning addMbrCode" );
paragraph = body.appendParagraph('Beginning addMbrCode.');
// Exception: Unexpected error while getting the method or property openById on object SpreadsheetApp.
// const ssId = PropertiesService.getScriptProperties().getProperty('ssId');
// var sheet = SpreadsheetApp.openById("[ssId]").getSheetByName('Sheet1');
// var sheet = SpreadsheetApp.openById("ssId").getSheetByName('Sheet1');
// Exception: Invalid argument: url
const ssUrl = PropertiesService.getScriptProperties().getProperty('ssUrl');
var sheet = SpreadsheetApp.openByUrl("ssUrl").getSheetByName('Sheet1');
myAddForm = [ fName, lName, inEmail, fallNum, winNum, sprNum];
var fName = myAddForm[0];
var lName = myAddForm[1];
var inEmail = myAddForm[2];
var fallNum = myAddForm[3];
var winNum = myAddForm[4];
var sprNum = myAddForm[5];
var retCd = '';
/**
* 10 - successful add
* 20 - duplicate - not added
*/
var combNameRng = sheet.getRange(2, 4, numRows).getValues();
var inCName = (fName + '.' + lName).toString().toLowerCase();
if (combNameRng.indexOf(inCName) > 0 ) {
console.log("Alert: Not adding duplicate "
+ fName + ' ' + lName + " retCd: " + 20 );
paragraph = body.appendParagraph("Not adding duplicate "
+ fName + ' ' + lName + " retCd: " + 20);
retCd = 20;
return retCd;
}
sheet.appendRow([fName.toString().toLowerCase()
, lName.toString().toLowerCase()
,
, inEmail.toString().toLowerCase()
]);
const currRow = sheet.getLastRow().toString();
);
retCd = 10;
return retCd;
}
If this makes a difference, here is the javascript from the body of my html in the dialog window.
<script>
document.querySelector("#myAddForm").addEventListener("submit",
function(e)
{
alert('begin addEventListener');
e.preventDefault(); //stop form from submitting
var retCd = google.script.run.addMbrCode(this); // client side validation
document.getElementById('errMsg').textContent = 'Successful member
return false; // do not submit - redisplay html
}
);
</script>
Removed unneeded coding detail
Per #iansedano I created an object/array to use instead of this and added the successhandler and failurehandler. In either case I want to see the html again with my message. This is the current script. Response is so doggy I am not seeing alerts, Logger.log, or console.log. Crazy shoppers using my internet!
<script>
document.querySelector("#myRmvForm").addEventListener("submit",
function(e)
// removed alerts and logging
// removed client side validation for simplicity
cSideValidate();
// Then we prevent the form from being submitted by canceling the event
event.preventDefault();
});
function cSideValidate() {
dataObj = [
document.getElementById('fName').value,
document.getElementById('lName').value,
document.getElementById('email').value
];
var retCd = google.script.run.withSuccessHandler(serverReply)
.withFailureHandler(serverReply)
.rmvMbrCode(dataObj); // server side validation
}
function serverReply {
// logic to set the correct message - this is an example
document.getElementById('errMsg').textContent
= 'Successful delete using email.';
}
</script>
Nothing is being added to my spreadsheet so the server side code is not working. I see my loggin so I know it is getting there.
You're getting ssId from the script properties and assigning it to the ssId variable, but then you pass a string ("ssId") to the openById() function, not the value of the variable.
Try the following please:
const ssId = PropertiesService.getScriptProperties().getProperty('ssId');
var sheet = SpreadsheetApp.openById(ssId).getSheetByName('Sheet1');

Getting all the Google Ads Labels from MCC. Also the onces created by other users within a client account

Google Ad Scripts makes it possible to get the labels of child/client accounts. But not the onces, who are created by a client itself. Is there a way to get ALL the labelnames?
I tried serveral script, but all are returning the MCC labels
function getAllAccountLabels() {
var labelIterator = AdsManagerApp.accountLabels().get();
while (labelIterator.hasNext()) {
var label = labelIterator.next();
Logger.log('Label with id = %s and text = %s was found.', label.getId().toFixed(0), label.getName());
}
}
There is a difference in handling the MCC labels.
AdsManagerApp.accounts().withCondition( 'LabelNames CONTAINS "test"' ).get();
And
var accountIterator = AdsManagerApp.accounts().get();
while (accountIterator.hasNext()) {
var account = accountIterator.next();
var accountName = account.getName();
var labelIterator = account.labels().get();
while (labelIterator.hasNext()) {
var label = labelIterator.next();
var labelName = label.getName();
if( labelName.match(/test/i) ) {
Logger.log( accountName+" "+labelName );
}
}
}
WithCondition is not returning the user-level label names!

Function works as expected when called from function using XMLHttpRequest, but fails when called from a function using EventSource. Why is this?

I'm working on creating a basic messenger using Javascript. I have three functions in a separate js file called loadMessage, messageListener, and displayMessage.
The function loadMessage makes a call to my database for all existing messages, and then calls displayMessages to construct some divs which I use to show the messages I got from the server. These divs are created to appear under each other, with the bottom div being the newly created one showing the latest message.
Once all the messages have been created loadMessage then calls messageListener. This function 'listens' for any new messages which might appear on the database. If any appear then messageListener calls displayMessage. I expect this to create a new div at the bottom of my other divs as before, however when it calls displayMessage the behaviour is completely different than when loadMessage calls displayMessage.
Specifically, it does not create a new div but instead just changes the text in an existing div which appears anywhere within the newly created divs (for example, the div which displays the first message or one somewhere in the middle).
My HTML and PHP files all behave as expected, so I think my issue is somewhere in these three functions.
How can I fix this to behave as expected?
Code:
// Loads chat messages history and listens for upcoming ones.
function loadMessages(userID, contactID) {
contactIDGlobal = contactID;
//load existing messages
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
var param = "userID="+userID+"&contactID="+contactID+"&date="+date;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","Interface-getMessage.php?", true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send(param);
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//retrives a string of all past messages
var messageString = xmlhttp.responseText;
//parse string to get messages.
var parseMessageString = messageString.split('-');
for (var i = 0; parseMessageString[i] !== null && parseMessageString[i] !== ''; i = i+5){
var contactID = parseMessageString[i];
var senderID = parseMessageString[i+1];
var message = parseMessageString[i+2];
var time = parseMessageString[i+3];
var mID = parseMessageString[i+4];
displayMessage(userID, senderID, contactID, message, date, time, mID);
}
}
};
//listen for new messages
messageListener(userID, contactID);
}
function messageListener(userID, contactID){
if(typeof(EventSource)!=="underfined") {
var newMessage = new EventSource("testerfile.php?userID="+userID+"&contactID="+contactID);
newMessage.onmessage = function(event) {
var newMessageData = event.data;
var parseNewMessage = newMessageData.split('-');
//sender ID may be different to the userID due to the way that messages are stored on the server. Received messages have a different sender.
var senderID = parseNewMessage[0];
var contactID = parseNewMessage[1];
var message = parseNewMessage[2];
var date = parseNewMessage[3];
var time = parseNewMessage[4];
var messageID = parseNewMessage[5];
console.log(event.data);
displayMessage(userID, senderID, contactID, message, date, time, messageID);
};
}else {
document.getElementById("messages").innerHTML = "Your browser does not support this";
}
}
// Displays a Message in the UI.
function displayMessage(userID, senderID, contactID, nMessage, date, time, id){
var messageListElement = document.getElementById('messages');
var messageInputElement = document.getElementById('message');
// If an element for this message already exists, then get it
var id = id;
var div = document.getElementById(id);
// If an element for that message does not exists yet we create it.
if (!div) {
var container = document.createElement('div');
if (userID == senderID){
container.innerHTML = SENDER_MESSAGE_TEMPLATE;
}else{
container.innerHTML = MESSAGE_TEMPLATE;
}
div = container.firstChild;
div.setAttribute('id', id);
for (var i = 0; i < messageListElement.children.length; i++) {
var child = messageListElement.children[i];
}
messageListElement.insertBefore(div, child);
}
var messageElement = div.querySelector('.message');
messageElement.textContent = nMessage;
// Replace all line breaks by <br>.
messageElement.innerHTML = messageElement.innerHTML.replace(/\n/g, '<br>');
}
// Template for messages.
var SENDER_MESSAGE_TEMPLATE =
'<div class="sender_message-container">' +
'<div class="message"></div>' +
'</div>';
var MESSAGE_TEMPLATE =
'<div class="message-container">' +
'<div class="message"></div>' +
'</div>';
The problem was coming from the date being returned as y-m-d, and the parser using "-". This mean I was creating a time var which was the month of my date, and the message ID as the day. I made the alteration below to fix this...
var newMessageData = event.data;
var parseNewMessage = newMessageData.split('-');
//sender ID may be different to the userID due to the way that messages are stored on the server. Received messages have a different sender.
var senderID = parseNewMessage[0];
var contactID = parseNewMessage[1];
var message = parseNewMessage[2];
var date = parseNewMessage[3]+"-"+parseNewMessage[4]+"-"+parseNewMessage[5];
var time = parseNewMessage[6];
var messageID = parseNewMessage[7];

Trying to understand getThreads in GAS

I am new to app script and I am trying to read an email from my inbox. I thought that getThreads would do the job but I still don't fully understand how to use it. When I try to execute the code I wrote below it comes up with a null error.
Looking at the documentation of getThreads(), they use the example:
// Log the subject lines of the threads labeled with MyLabel
var label = GmailApp.getUserLabelByName("MyLabel");
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
Logger.log(threads[i].getFirstMessageSubject());
}
what does "MyLabel" stand for?
This is the code i tried that failed
function myFunction() {
var label = GmailApp.getUserLabelByName('bobtheman#gmail.com');
var threads = label.getThreads();
for (var t in threads) {
var thread = threads[t];
// Gets the message body
var message = thread.getMessages()[0].getPlainBody();
}
GmailApp.sendEmail('barbrabat#gmail.com', 'hola', message)
}
MyLabel is the label of the email. It depends whether you added a label to a specific email or not. You can use the search method instead.
function myFunction(){
var label = 'yourLabel'; // if no label, remove the label in search
// it would be better if you add a label to a specific email for fast and more precise searching
var searchEmail = GmailApp.search('from:me subject:"' + subject + '" label:' + label + '');
var threadId = searchEmail[0].getId(); // get the id of the search email
var thread = GmailApp.getThreadById(threadId); // get email thread using the threadId
var emailMsg = thread.getMessages()[0]; // get the content of the email
var emailContent = emailMsg.getPlainBody(); // get the body of the email
// check using log
Logger.log(emailContent);
// how to open log
// Ctrl + Enter
// Run this function before checking the log
}
Thanks

Categories