Recent email of the thread - Gmail - google-apps-script

Can anyone help me with a query that I can use to extract data from my Gmail?
Here are the requirements,
Date range, so I can select a specific date
Subject of the email
Date of the email
Body of recent email of the thread
Sender of the recent email of the thread
Receiver of the recent email of the thread
var ui = SpreadsheetApp.getUi();
function onOpen(e) {
ui.createMenu("Gmail Manager").addItem("Get Emails", "getEmails").addToUi();
}
function getEmails() {
const threads = GmailApp.getInboxThreads();
for (let i = 0; i < threads.length; i++) {
const msgs = threads[i].getMessages();
const lastmsg = msgs[msgs.length - 1];
var firstmessage = thread.getMessages()[0];
var recentmessagesender = firstmessage.getFrom();
var recentMessageSubject = thread.getFirstMessageSubject();
}
}

If you want to retrieve the recent message of each thread, you can try this:
Code
function getEmails() {
let threads = GmailApp.getInboxThreads();
for (let i=0; i< threads.length; i++) {
let thread = threads[0];
let messages = thread.getMessages();
let recentMessage = messages[0];
let recentMessageSender = recentMessage.getFrom();
let recentMessageReceiver = recentMessage.getTo();
let recentMessageSubject = recentMessage.getSubject();
let recentMessageDate = recentMessage.getDate();
let recentMessageBody = recentMessage.getPlainBody();
}
}
Explanation
The above snippet gathers all the threads and then for each thread it retrieves the first message, this being denoted by the messages[0]. Afterwards, the sender, received, subject, date and body are retrieved using the specific methods for the GmailMessage object.
However, depending on what exactly you plan on doing with the information obtained, you can either use :
console.log in order to display it to the logger
OR if you want to write it to the spreadsheet, you will have to
use the SpreadsheetApp service, something similar to this:
// add this outside the `for` loop
let activeSheet = SpreadsheetApp.getActiveSheet();
// add this inside the `for` loop
activeSheet.getRange(i+1,1).setValue(recentMessageSender);
activeSheet.getRange(i+1,2).setValue(recentMessageReceiver);
When writing to the spreadsheet, you will have to take into account the range you want to paste the date onto. In the above example, the first row will correspond to the first message of the first thread, the second row will correspond to the first message of the second thread and so on.
Reference
Apps Script GmailMessage Class;
Apps Script Sheet Class - getRange();
Apps Script Range Class - setValue().

Related

How do I resolve OAuth scopes to GSheets and in call out to a GClassroom function, in order to grab assignment data and post to GSheet?

I don't know JSON, so I'm trying to code this with GScript. I want to combine a call out to this function that gets Classroom info from a working script function that posts array info to a GSheet.
The first time I ran the script below, I triggered the API authentication and got the information I needed, although only in Logger.
var email = "my_email#something.org";
function countWork(email) {
var courseId = "valid_courseId";
var data = ""; // String of resulting information from loop below
var assignments = Classroom.Courses.CourseWork.list(courseId);
var length = assignments.courseWork.length;
// Loop to gather info
for (j = 0; j < length; j++) {
var assignment = assignments.courseWork[j];
var title = assignment.title;
var created = assignment.creationTime;
Logger.log('-->Assignment No. %s -->%s -->(%s)',j+1,title,created);
}
return data;
}
But for some reason, I can't OAuth scopes on this version of the script where I've substituted the array I need for posting to GSheet. I get the error message "Classroom is not defined (line 7...)." What do I need to do so Classroom.Courses.etc will be recognized?
var email = "my_email#something.org";
function extractAssignmentData(email) {
var courseId = "valid_courseId"; //
var data = []; // Array of resulting information from loop below
var assignments = Classroom.Courses.CourseWork.list(courseId); // error: Classroom is not defined (line 7)
var length = assignments.courseWork.length;
// Loop to gather data
for (j = 0; j < length; j++) {
var assignment = assignments.courseWork[j];
// types of information: description, creationTime, updateTime, dueDate, dueTime, workType
var title = assignment.title;
var created = assignment.creationTime;
var info = [j+1,title,created];
data.push(info);
}
return data;
}
Thanks so much, Tanaike, for your helpful responses!
Based on your suggestions, I was able to find this post, which explicitly described how to consult the manifest file, and how to incorporate scopes into the appsscript.json.
I'm still not sure why the first version of the script triggered the scope
"https://www.googleapis.com/auth/classroom.coursework.students"
while the second instead added this one:
"https://www.googleapis.com/auth/classroom.coursework.me.readonly"
But, since I now know how to add what I need and can access the Classroom info I need, it's a mute point. Thanks, again!
(I'm not sure how to mark your comment as the answer to my question -- you should get the points!)

Gmail apps script edit body before forwarding

I'm using Gmail apps script to forward emails with a certain label ... But I'd like to edit the body of the message prior to forwarding.
function fwdFB(){
var label = GmailApp.getUserLabelByName('fb');
var threads = label.getThreads();
for(var m in threads){
var messages = threads[m].getMessages();
for(var y in messages){ messages[y].forward('w#yahoo.com',{from:'webmaster#gmail.com'}) }
threads[m].moveToTrash();
}
}
I'm unclear as to how to insert the getBody() method to edit the message. (Specifically, I want to delete a certain HTML chunk from the message. It's the same chunk in each message.)
The options of forward(recipient, options) do not offer an endpoint to modify the message body. You'll have to do it instead manually, by sending a message after modifying the body as desired.
Sample:
function fwdFB(){
var label = GmailApp.getUserLabelByName('fb');
var threads = label.getThreads();
for(var m in threads){
var messages = threads[m].getMessages();
for(var y in messages){
var oldBody = messages[y].getBody();
var newBody = oldBody.substring(1, 10)+" PS: This is a modification."
var oldSubject = messages[y].getSubject();
var newSubject = "Fwd: "+ oldSubject;
GmailApp.sendEmail('w#yahoo.com', newSubject, newBody, {from:'webmaster#gmail.com'})
}
threads[m].moveToTrash();
}
}
UPDATE
If it is important for you to preserve the message history, you need to perform additional steps to thread the message.
#tehhowch provides a good example of how to do so.

Getting the body of individual emails from gmail to google sheets

I'm really new at using Google Apps Script, so if what I'm trying doesn't make sense, or just isn't possible please let me know.
Everyday I get several emails that look like the following:
Your Name: FirstName LastName
Phone Number: 555 867 5309
Email Address: FakeEmail#email.com
What do you need help with? Request someone makes.
I'm attempting to automatically send the body of these emails to a new line in a Google Sheet when they come in.
As of right now I have every email get the label "myLabel" when it comes in. I then run the following script, which is a slightly modified version of something I found here:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("MyLabel");
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 msg = messages[j].getBody();
ss.appendRow([msg])
}
threads[i].removeLabel(label);
}
}
I'm attempting to run this code with a timer trigger every 15 minutes. The issue I've run into is that every time the code runs it pulls from every email in the thread. I would like it to just pull from the emails that are new since the last time it ran. Any advice would be greatly appreciated.
Why not mark the messages as read when you finish processing them? Here is a sample from one of my scripts.
var pendingEmailLabel = "MyLabel";
var threads = GmailApp.getUserLabelByName(pendingEmailLabel).getThreads();
for (var t = 0; t < threads.length; ++t) {
var thread = threads[t];
var messages = thread.getMessages();
for (var m = 0; m < messages.length; ++m) {
var message = messages[m];
if (message.isUnread()) {
// INSERT YOUR CODE HERE THAT TAKES ACTION ON THE MESSAGE
message.markRead();
}
}
}
}

google script to pull recipient of an email in a label

I have automatic email alerts that go into a label in my inbox (through the reply-to) and are also sent to users (through the to: part of the email).
I'm looking to add onto my script that pulls information in the body of the email. Ultimately, I want to pull the recipient of the email (in the to: part) and put that in Column B of a google sheet. Any insight will be greatly appreciated.
Script:
// Modified from http://pipetree.com/qmacro/blog/2011/10/automated-email-to-task-mechanism-with-google-apps-script/
// Globals, constants
var LABEL_PENDING = "Example label/PENDING";
var LABEL_DONE = "Example label/DONE";
// processPending(sheet)
// Process any pending emails and then move them to done
function processPending_(sheet) {
// Date format
var d = new Date();
var date = d.toLocaleDateString();
// Get out labels by name
var label_pending = GmailApp.getUserLabelByName(LABEL_PENDING);
var label_done = GmailApp.getUserLabelByName(LABEL_DONE);
// The threads currently assigned to the 'pending' label
var threads = label_pending.getThreads();
// Process each one in turn, assuming there's only a single
// message in each thread
for (var t in threads) {
var thread = threads[t];
// Gets the message body
var message = thread.getMessages()[0].getBody();
// Processes the messages here
orderinfo = message.split("example split");
rowdata = orderinfo[1].split(" ");
// Add message to sheet
sheet.appendRow([rowdata[1]]);
// Set to 'done' by exchanging labels
thread.removeLabel(label_pending);
thread.addLabel(label_done);
}
}
// main()
// Starter function; to be scheduled regularly
function main_emailDataToSpreadsheet() {
// Get the active spreadsheet and make sure the first
// sheet is the active one
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.setActiveSheet(ss.getSheets()[0]);
// Process the pending emails
processPending_(sh);
}
You can access the recipient data with the getTo() function of the message. You could simply add a line that saves itin the column
//Gets the message body and recipent
var message = thread.getMessages()[0].getBody();
var recipient = thread.getMessages()[0].getTo();
//...
// Add message and recipient to sheet
sheet.appendRow([rowdata[1], recipient]);
More info on the function of the gmailMessage class -> https://developers.google.com/apps-script/reference/gmail/gmail-message

getMessageById() slows down

I am working on a script that works with e-mails and it needs to fetch the timestamp, sender, receiver and subject for an e-mail. The Google script project has several functions in separate script files so I won't be listing everything here, but essentially the main function performs a query and passes it on to a function that fetches data:
queriedMessages = Gmail.Users.Messages.list(authUsr.mail, {'q':query, 'pageToken':pageToken});
dataOutput_double(sSheet, queriedMessages.messages, queriedMessages.messages.length);
So this will send an object to the function dataOutput_double and the size of the array (if I try to get the size of the array inside the function that outputs data I get an error so that is why this is passed here). The function that outputs the data looks like this:
function dataOutput_double(sSheet, messageInfo, aLenght) {
var sheet = sSheet.getSheets()[0],
message,
dataArray = new Array(),
row = 2;
var i, dateCheck = new Date;
dateCheck.setDate(dateCheck.getDate()-1);
for (i=aLenght-1; i>=0; i--) {
message = GmailApp.getMessageById(messageInfo[i].id);
if (message.getDate().getDate() == dateCheck.getDate()) {
sheet.insertRowBefore(2);
sheet.getRange(row, 1).setValue(message.getDate());
sheet.getRange(row, 2).setValue(message.getFrom());
sheet.getRange(row, 3).setValue(message.getTo());
sheet.getRange(row, 4).setValue(message.getSubject());
}
}
return;
};
Some of this code will get removed as there are leftovers from other types of handling this.
The problem as I noticed is that some messages take a long time to get with the getMessageById() method (~ 4 seconds to be exact) and when the script is intended to work with ~1500 mails every day this makes it drag on for quite a while forcing google to stop the script as it takes too long.
Any ideas of how to go around this issue or is this just something that I have to live with?
Here is something I whipped up:
function processEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var messages = Gmail.Users.Messages.list('me', {maxResults:200, q:"newer_than:1d AND label:INBOX NOT label:PROCESSED"}).messages,
headers,
headersFields = ["Date","From","To","Subject"],
outputValue=[],thisRowValue = [],
message
if(messages.length > 0){
for(var i in messages){
message = Gmail.Users.Messages.get('me', messages[i].id);
Gmail.Users.Messages.modify( {addLabelIds:["Label_4"]},'me',messages[i].id);
headers = message.payload.headers
for(var ii in headers){
if(headersFields.indexOf(headers[ii].name) != -1){
thisRowValue.push(headers[ii].value);
}
}
outputValue.push(thisRowValue)
thisRowValue = [];
}
var range = ss.getRange(ss.getLastRow()+1, ss.getLastColumn()+1, outputValue.length, outputValue[0].length);
range.setValues(outputValue);
}
}
NOTE: This is intended to run as a trigger. This will batch the trigger call in 200 messages. You will need to add the label PROCESSED to gmail. Also on the line:
Gmail.Users.Messages.modify( {addLabelIds:["Label_4"]},'me',messages[i].id);
it shows Label_4. In my gmail account "PROCESSED" is my 4th custom label.