I created a function that search's my inbox in Gmail and then classifies each massage in 3 categories (name, email and body). Then it pastes it in 3 columns in a Google Sheet. But, when I run it will only paste the name and email on the first 2 columns. The problems is with the body. Even though, when i run Logger.log(d.getPlainBody());
it shows the body text I am looking for.
The code I am using:
// extract emails from label in Gmail
function extractEmails() {
// get the spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
// get all email threads that match label from Sheet
var threads = GmailApp.getInboxThreads();
// get all the messages for the current batch of threads
var messages = GmailApp.getMessagesForThreads(threads);
var emailArray = [];
// get array of email addresses
messages.forEach(
function(message) {
message.forEach(
function(d) {
emailArray.push(d.getFrom(),d.getTo(),d.getPlainBody());
Logger.log(d.getPlainBody());
});
});
// de-duplicate the array
var uniqueEmailArray = emailArray.filter(function(item, pos) {
return emailArray.indexOf(item) == pos;
});
var cleanedEmailArray = uniqueEmailArray.map(
function(el) {
var matches = el.match(/\s*"?([^"]*)"?\s+<(.+)>/);
if (matches) {
name = matches[1];
email = matches[2];
body = matches[3];
}
return [name, email, body];
});
// clear any old data
sheet.getRange(2,1,sheet.getLastRow(), 3).clearContent();
// paste in new names and emails
var printing = sheet.getRange(2 ,1,cleanedEmailArray.length, 3);
printing.setValues(cleanedEmailArray);
}
Your logic seems faulty, especially on the map function. You are actually matching every element, not per message. And your regex is only capturing 2 patterns so it was expected for matches[3]
to return blank.
I modified your code a little bit. Here are they:
getTo
as you are not using it. But if you are, feel free to add it again. // get array of email addresses
messages.forEach(function(message) {
message.forEach(function(d) {
// Push the data as array to easily process them
// Removed getTo as you only are getting name and email from getFrom data based on your regex
emailArray.push([d.getFrom(),d.getPlainBody()]);
});
});
forEach
. This is possible since we made the message data as array above. var cleanedEmailArray = [];
uniqueEmailArray.forEach(function(message){
// match name and email from pattern "name <email>" in d.getFrom()
// only pass match[1] and match[2], since match[0] = message[0]
[, name, email] = message[0].match(/\s*"?([^"]*)"?\s+<(.+)>/);
// get body from d.getPlainBody()
body = message[1];
cleanedEmailArray.push([name, email, body])
});
printing
so I combined the 2 lines // paste in new names and emails
sheet.getRange(2 ,1,cleanedEmailArray.length, 3).setValues(cleanedEmailArray);
This is what your code will look like:
function extractEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var threads = GmailApp.getInboxThreads();
var messages = GmailApp.getMessagesForThreads(threads);
var emailArray = [], cleanedEmailArray = [];
messages.forEach(function(message) {
message.forEach(function(d) {
emailArray.push([d.getFrom(),d.getPlainBody()]);
});
});
var uniqueEmailArray = emailArray.filter(function(item, pos) {
return emailArray.indexOf(item) == pos;
});
uniqueEmailArray.forEach(function(message){
[, name, email] = message[0].match(/\s*"?([^"]*)"?\s+<(.+)>/);
body = message[1];
cleanedEmailArray.push([name, email, body])
});
sheet.getRange(2,1,sheet.getLastRow(), 3).clearContent();
sheet.getRange(2 ,1,cleanedEmailArray.length, 3).setValues(cleanedEmailArray);
}