Extract substring of e-mail message body to google spreadsheet - javascript

I'm using google app scripts to extract e-mail data into a google spreadsheet. I've got the below working code that I am trying to modify. I'm sure there's a smarter way ... but for now this works
function emf() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("tkh_emf");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var name = messages[j].getPlainBody().split("Name*:")[1].split("\n")[0];
var email = messages[j].getPlainBody().split("E-mail*:")[1].split("\n")[0];
var phone = messages[j].getPlainBody().split("Phone:")[1].split("\n")[0];
var addr = messages[j].getPlainBody().split("Street Address:")[1].split("\n")[0];
var city = messages[j].getPlainBody().split("City*:")[1].split("\n")[0];
var find = messages[j].getPlainBody().split("hear about us?*:")[1].split("\n")[0];
var sub = messages[j].getSubject().split("Feedback via the ")[1].split("[")[0];
var num = messages[j].getSubject().split("Feedback via the ")[1].split("[")[1].split("]")[0];
var dat = messages[j].getDate();
var referrer = messages[j].getPlainBody().split("Referer URL:")[1].split("\n")[0];
ss.appendRow([name, email, phone, addr, city, find, sub, num, dat, referrer])
}
threads[i].removeLabel(label);
}
}
My e-mail looks like this:
Name*: name
E-mail*: email#gmail.com
Phone:
Street Address: 3704 17th St.
City*: city
How did you hear about us?*: Search engine results
Brief description of work requested*: work here
So my code extracts the appropriate strings for each field except the 'Phone' and 'Address' fields which are not required. If these fields are not filled, then the e-mail does not have the words 'Phone' or 'Street Address' so the lines for var phone and var addr fail because you can't split a null. Is there a way to insert an if string 'Phone' and 'Street Address' exists then execute the above? Thanks.

You were right that you'll need regex to accomplish the job (or it'll certainly make it easier). I've written a simple script in Codepen that'll show you how to use the regex.
In my script, I split the body data at the newline character, and then loop through the resulting array of lines. I pipe each line into a function that captures and returns the text you need. You needn't pipe in anything other the line--it detects what the name of the field is, and uses it appropriately, based on your current format.
In your own code, you would have to do the following to msg before placing it into your spreadsheet:
var msg = messages[j].getPlainBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
var bodyLines = msg.split("\n");
var fields = [];
for (var k = 0; k < bodyLines.length; k++) {
fields.push(getText(bodyLines[k]));
}
// do something with the resulting array of fields here
Here's the getText(str) function (can also be found in Codepen):
function getText(str) {
var fieldRe = new RegExp("(.+)\:", "g");
var fieldGroups = fieldRe.exec(str);
var fieldName = fieldGroups[1].split("*")[0];
fieldName = (fieldName == null) ? fieldGroups[1] : fieldName;
fieldName = fieldName.replace(/[\!\#\#\$\%\^\&\*\(\)\-\_\+\=\`\~\[\]\{\}\\\/\|\:\;\'\"\<\>\,\.\?]/g, function transformIllegal(x) {
return "\\" + x;
});
var re = new RegExp(`${fieldName}\\*?\\:\\s+(.*)`, "g");
var groups = re.exec(str);
var out = (groups == null) ? "" : groups[1];
return out;
}

Here's what I'm ending with. Not sophisticated but works.
function emf() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("tkh_emf");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var name = messages[j].getPlainBody().split("Name*:")[1].split("\n")[0];
var email = messages[j].getPlainBody().split("E-mail*:")[1].split("\n")[0];
try {var phone = messages[j].getPlainBody().split("Phone:")[1].split("\n")[0];}
catch(e){var phone = "-";}
try {var addr = messages[j].getPlainBody().split("Street Address:")[1].split("\n")[0];}
catch(e){var addr = "-";}
var city = messages[j].getPlainBody().split("City*:")[1].split("\n")[0];
var find = messages[j].getPlainBody().split("hear about us?*:")[1].split("\n")[0];
try {var referrer = messages[j].getPlainBody().split("Referrer Name:")[1].split("\n")[0];}
catch(e){var referrer = "-";}
var sub = messages[j].getSubject().split("Feedback via the ")[1].split("[")[0];
var num = messages[j].getSubject().split("Feedback via the ")[1].split("[")[1].split("]")[0];
var dat = messages[j].getDate();
ss.appendRow([name, email, phone, addr, city, find, referrer, sub, num, dat])
}
threads[i].removeLabel(label);
}
}

Related

google scripts throwing not a function error for getMessages()

I am trying to create a script for an autoreply function. I am currently trying to grab each of the emails assigned to a specific label and grab specific details off of each email, however I am receiving an error stating TypeError: threads.getMessages is not a function, even though I have triple checked that this is, indeed, a function of the GMAIL scripting. Have I done something wrong here in this code that may be causing this error?
var labelName = "auto-reply-incoming";
var receivedCount = 0;
// extract emails from label in Gmail
function extractEmails() {
// get all email threads that match label
var receivedSearchQuery = "label:"+labelName+" -is:sent";
var threads = GmailApp.search(receivedSearchQuery, 0, 500);
for (var i=0; i<threads.length; i++) {
//count received emails in label
receivedCount = receivedCount + threads[i].getMessageCount();
//get body of each email
var message = threads.getMessages()[i].getBody();
//get recipient of each email
var recipient = threads.getMessages()[i].getTo();
}
Logger.log(receivedCount);
Logger.log(recipient);
}
The problem occurs because the code is using the threads iterator that might be bigger than the number of messages on certain threads, more specifically, the problem is in the following lines:
//get body of each email
var message = threads.getMessages()[i].getBody();
//get recipient of each email
var recipient = threads.getMessages()[i].getTo();
Here is a quick fix (replace the above, by the following)
var messages = threads[i].getMessages();
for( j = 0; j < messages.length; j++){
//get body of each email
var message = messages[j].getBody();
//get recipient of each email
var recipient = messages[j].getTo();
}
Note: Logger.log(recipient) will log the recipient of the last message of the last thread.
Try this:
function extractEmails() {
var labelName = "auto-reply-incoming";
var receivedCount = 0;
var receivedSearchQuery = "label:" + labelName + " -is:sent";
var ts = GmailApp.search(receivedSearchQuery, 0, 500);
var a = [];
ts.forEach((t, i) => {
let ms = t.getMessages();
ms.forEach((m, j) => {
let msg = m.getBody();
let rec = m.getTo();
a.push({ threadindex: j, messageindex: i, message: msg, recipient: rec })
});
});
Logger.log(JSON.stringify(a));
}

Extract data from Email Body

So i'm writing a script to automatically collect emails to a Google spreadsheet. I would like from this email to extract some details like the email address, the name, the address, the phone number. So far i managed to extract the date, the subject, the sender details and the body contents. Below i'll attach the email body and also the code i've written so far! If you have contact me directly at this emails.
This a code i've tried so far:
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu("KingBoss Menu").addItem("Get Emails", "getGmailEmails").addToUi();
}
function getGmailEmails() {
var label = GmailApp.getUserLabelByName("warranty");
var threads = label.getThreads();
for(var i = threads.length - 1; i >=0; i--) {
var messages = threads[i].getMessages();
for (var j = 0; j <messages.length; j++) {
var message = messages[j];
extractDetails(message);
GmailApp.markMessageRead(message);
}
}
}
function extractDetails(message) {
var dateTime = message.getDate();
var subjectText = message.getSubject();
var senderDetails = message.getFrom();
var bodyContents = message.getPlainBody();
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
activeSheet.appendRow([dateTime, senderDetails, subjectText, bodyContents]);
}

Receiving [Ljava.lang.Object in Apps Script (bringing attachment name from Gmail to Sheets)

Have been working on an Apps Script to bring Gmail message information (sender, subject, link, attachment) into a Google Sheet, but not able to bring the title of the attachment over successfully (attachment name field in Google Sheet reads like [Ljava.lang.Object;#127afe9; it appears to be related to the attachments array, but I cannot figure it out. Have tried the solutions offered in What does "[Ljava.lang.Object;#" mean?, but no luck.
function emailToSheet() {
var label = GmailApp.getUserLabelByName('New TODO'); // Find messages with label
var changeLabel = GmailApp.getUserLabelByName('TODO'); // Change message label to
var ss = SpreadsheetApp.openById('xxxx'); // Append to spreadsheet
var sh = ss.getSheetByName("Email"); //On this sheet
var threads = label.getThreads();
for (var i=0; i<threads.length; i++){
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++) {
var sent = messages[j].getDate();
var from = messages[j].getFrom();
var subject = messages[j].getSubject();
// Get attachment name
var attachments = messages[j].getAttachments();
var attachmentName = [];
for (var k=0; k<attachments.length; k++) {
var attachmentName = attachments[k].getName();
}
var messageId = messages[j].getId();
var messageUrl = "https://mail.google.com/mail/u/0/#inbox/" + messageId;
ss.appendRow([sent, from, subject, attachmentName, messageUrl])
}
threads[i].removeLabel(label);
threads[i].addLabel(changeLabel);
}
}
I'm thinking that you want this:
var attachmentName = [];
for (var k=0; k<attachments.length; k++) {
var attachmentName = attachments[k].getName();
}
to be this:
var attachmentName = [];
for (var k=0; k<attachments.length; k++) {
attachmentName.push(attachments[k].getName());
}
and maybe this:
ss.appendRow([sent, from, subject, attachmentName, messageUrl])
to be this:
ss.appendRow([sent, from, subject, attachmentName.join(" "), messageUrl])

Google Sheet Import Ljava.lang.Object error

I have pieced together a few different scripts to get this to work but I cant seem to get the code to put the data in correctly.
Email Input:
*Status:*
*Date:* 03/31/2020
*WorkOrder:* 123456-1
*DMSShipDate:* 03/31/2020
*PONumber:* 8675309
*Company:* Test
Script
var ui = SpreadsheetApp.getUi();
function onOpen(e){
ui.createMenu("Import Email").addItem("Import Email", "getGmailEmails").addToUi();
}
function getGmailEmails(){
if (Session.getActiveUser().getEmail() != "email#gmail.com"){
Browser.msgBox("Please log in as email#gmail.com");
return;
}
var label = GmailApp.getUserLabelByName("ImportMe");
var threads = label.getThreads();
for(var i = threads.length - 1; i >=0; i--){
var messages = threads[i].getMessages();
for (var j = 0; j <messages.length; j++){
var message = messages[j];
extractDetails(message);
GmailApp.markMessageRead(message);
}
threads[i].removeLabel(label);
}
}
function extractDetails(message){
var bodyContents = message.getPlainBody();
var status = bodyContents.match(/\*Status:\*(.*) /);
var dateEntered = bodyContents.match(/\*Date:\*(.*) /);
var workOrder = bodyContents.match(/\*WorkOrder:\*(.*) /);
var dmsShipDate = bodyContents.match(/\*DMSShipDate:\*(.*) /);
var poNum = bodyContents.match(/\*PONumber:\*(.*) /);
var company = bodyContents.match(/\*Company:\*(.*) /);
var activeSheet = SpreadsheetApp.getActiveSheet();
activeSheet.appendRow([status, dateEntered, workOrder, dmsShipDate, poNum, company]);
}
Result:
I get the following in each column:
[Ljava.lang.Object;#488e1851, [Ljava.lang.Object;#5c588720, etc, etc
I have tried JSON.Stringify and toString() but nothing seems to be able to get the data into the column correctly.
String.match returns a array. To get the captured group, index into that array:
bodyContents.match(/\*Status:\*(.*) /)[1];

If new contact get address, subject, message

I need a program for google script that tells me if I have an email address in my contacts or not.
I get many emails from vendors each day and many of them are completely new contacts. I need a program that makes a list of only the new contacts so I can decide which contact group to add them too.
Basic structure of what I'm looking for:
Will run this program every 5 minutes (I can set that up.)
-Checks emails with yellow or blue star for email address of recipient and sender. filters out my email address.
-Checks the email address against all my contacts. If the email address does not appear in my google contacts I need:
Email address, subject line, message text, additional thread message, additional thread message... in seperate columns in a spreadsheet.
I will then go through this information manually to decide which groups to put them in.
Thank you for your help!!!
UPDATE//////////////////////////////update.3
Here's where I'm at. This is working on and off. One time I run it it works, another time it doesn't. REally annoying. If anyone can see any glairing problems let me know. Especially hard to get the if sndr and if rcpnt to return false to run the rest of the program. I've tried about 20 ways!!!
//http://webapps.stackexchange.com/questions/9813/get-e-mail-addresses-from-gmail-messages-received
/////////////NESTED LOOP METHOD
function newEmailAddressList(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("NewEmails");
var range = sheet.getRange("A2:BA");
var addrA;
range.clearContent(); //May need to change this to my delete function to speed things up.
var contact = ContactsApp.getContacts();
for(var i = 0;i < contact.length;i++){
var addrA = [];
var start;
var addresses = contact[i].getEmails();
for(var j = 0;j < addresses.length;j++){
addrA.push(addresses[j].getAddress());
};
};
sheet.getRange('H1').setValue("List Created");
for (var i=0; i<50; i++){
var threads = GmailApp.getInboxThreads(0,50)[i];
var messages = threads.getMessages()[0];
var sndr = messages.getFrom().replace(/^.+<([^>]+)>$/, "$1"); //http://stackoverflow.com/questions/26242591/is-there-a-way-to-get-the-specific-email-address-from-a-gmail-message-object-in
var rcpnt = messages.getTo().replace(/^.+<([^>]+)>$/, "$1");
function contains(addrA, sndr) {
for (var i = 0; i < addrA.length; i++) {
if (addrA[i] === sndr) {
sheet.appendRow("Emails Match");
}else{
var dat = messages.getDate();
//var sndr = messages.getFrom();
//var rcpnt = messages.getTo();
var sub = messages.getSubject();
var msg = messages.getPlainBody();
var info = [dat,sndr,rcpnt,sub,msg];
sheet.appendRow(info); //appendRow only works with sheet class not range class
};
};
};
};
};
Well, I'll give you a start. And keep in my that I've never really worked with GmailApp in the past so all of this information is pretty much readily available to any who opens the code editor clicks on help and then clicks on API Reference. Everything you need to know about Google Scripts is right there organized about as well as it's ever been. They have really improved their documentation since the first time I've looked at it several years ago.
So I'm giving you some functions that will get all of your contact emails, your from emails from your inbox and and your emails.
function myContacts()
{
var s = '';
var br = '<br />';
var contact = ContactsApp.getContacts();
for(var i = 0;i < contact.length;i++)
{
var addrA = [];
var addresses = contact[i].getEmails();
for(var j = 0;j < addresses.length;j++)
{
s += addresses[j].getAddress() + br;
addrA.push(addresses[j].getAddress());
}
}
dispStatus('Contact Emails',s, 800, 400);
}
function MyFroms()
{
var threads = GmailApp.getInboxThreads();
var s = '';
for(var i = 0; i < threads.length; i++)
{
var msg = threads[i].getMessages();
for(var j = 0; j < msg.length;j++)
{
s += msg[j].getFrom() + '<br />';
}
}
dispStatus('My Messages', s , 800 , 400);
}
function MyMessages()
{
var threads = GmailApp.getInboxThreads();
var s = '';
for(var i = 0; i < threads.length; i++)
{
var msg = threads[i].getMessages();
for(var j = 0; j < msg.length;j++)
{
s += 'Message' + j+1 + '<br />';
s += msg[j].getFrom() + '<br />';
s += msg[j].getBody() + '<br />';
}
}
dispStatus('My Messages', s , 800 , 400);
}
function dispStatus(title,html,width,height)
{
var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
var width = typeof(width) !== 'undefined' ? width : 800;
var height = typeof(height) !== 'undefined' ? height : 400;
var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
var htmlOutput = HtmlService
.createHtmlOutput(html)
.setWidth(width)
.setHeight(height);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
}
It's not a complete answer. But hopefully it will encourage you to jump in get your feet wet and exercise your mental muscles and bring us back at least a partially working skeleton of a program that we can help you get running.

Categories

Resources