Removing "read" logic from gmail script - google-apps-script

I am fairly new to google app scripts and hoped you could help me… I am sure this is an easy question.
I am running the following script to archive old emails. It currently only archives read emails, but I would like to have it archive messages with these labels regardless of whether they are read or unread. Any help would be appreciated!
function archiveInbox4() {
// Every thread in your Inbox that is read, older than fourteen days, and not labeled "delete me".
var threads = GmailApp.search('label: inbox older_than:14d label:"Calendar"|"wacuho-acuho-i"|"professional-organizations"');
for (var i = 0; i < threads.length; i++) {
threads[i].moveToArchive();

There's a way that you can mark emails read first then archive them as read emails.
Sample code is like:
function markArchivedAsRead() {
var threads = GmailApp.search('label:unread -label:inbox');
GmailApp.markThreadsRead(threads);
};
However this operation can only be applied to at most 100 threads. To fix this, you have to manually do a search for "is:unread" and mark all of them as read before running the script, so that it starts with a clean slate. The script can only process 100 threads per run, so if you give it more than 100 on the first run, that'll obviously bust it. See the reference link.
You can also have this code to get it done by google apps script:
function markArchivedAsRead() {
var threads = GmailApp.search('is:unread');
for (var i = 0; i < threads.length; i++) {
GmailApp.markThreadRead(threads[i]);
}
};

Related

Using Gmail labels in Apps Script for Sheets

I am trying to evaluate emails with an existing label called "TestLabel" (applied via a simple Gmail filter on receipt), then once processed via a script called "extractDetails", remove the label. My problem is that old emails, that previously had the label but have already been processed, continue to meet the condition in subsequent executions. I have verified (at least visually) that the label is no longer attached. I have also turned off "conversation" view in Gmail, hoping/believing that the nested thread was the issue. Strangely, not all previous emails get reprocessed - but, for example, the most recent 35 or so from a list of hundreds. The only thing I've found that solves this is permanently deleting the prior emails, but I'd like to avoid doing so, and I am also curious to simply solve the problem.
My code is as follows:
function getGmailEmails(){
var label = GmailApp.getUserLabelByName('TestLabel');
var threads = label.getThreads();
var i = 0;
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);`
}
threads[i].removeLabel(label);
threads[i].markRead()
threads[i].moveToArchive(); ;
}
}
Thank you to this community for your assistance. Hopefully I posed this question properly.
Edit: This short script returns a value of 57, when the verfied # of labelled messages in Gmail is 2. The other 55 emails were, at one point, also labelled the same but have been processed and the label has been removed.
function getLabel () {
var label = GmailApp.search('label:TestLabel');
Logger.log(label[0].getMessageCount());
}
Further edit:
I changed the applied label to a new one in the Gmail Filter and the script. Oddly, the legacy emails still are captured - not only without the original label, but most certainly without the new one. I'm baffled.

Google Apps Script for loop not processessing all items from getThreads()

I am attempting to create a function that reads the body of emails and extracts parts to place in a sheet.
I am currently using the below code to pull the emails.
var label = GmailApp.getUserLabelByName("VOIDS");
var threads = label.getThreads();
for (var i = 0; i <= threads.length; i++)
{
var message = threads[i].getMessages();
var body = message[0].getPlainBody();
//email processing//
threads[i].removeLable(label)
}
I've got the loop to do what I need it to do as far as processing the email and placing it where I need it, however it seems to be skipping emails. I've left out the code for the process as it's just a bunch of split() functions on the body variable to extract the appropriate information and paste it into a sheet.
The total number of emails skipped varies based on how many it has to process, but re-running the script results in the same emails being skipped each time.
All emails are having their label removed and all emails are identical save for a few value changes.
This is my first time working with GmailApp outside of sending emails. I'm sure that this is something super simple that I'm just missing, but despite all my Google searching I can't seem to find a solution.
Thank you!
Please bear in mind that getThreads might not return all the threads in your mailbox.
From the official reference docs
getThreads()
Gets the threads that are marked with this label.
This calls fail when the size of all threads is too large for the system to handle. Where the thread size is unknown, and potentially very large, please use getThreads(start, max) and specify ranges of the threads to retrieve in each call.
Resources
https://developers.google.com/apps-script/reference/gmail/gmail-label#getthreads
Related
Trying to understand getThreads in GAS
Make getThreads() app script call count over 500
A thread can contain more than one email
The line var body = message[0].getPlainBody(); implies that you are only proceeding the body of the first message of each thread.
To apply your request t all emails, you need to create a second loop, iterating through each email of each thread.
Sample:
var label = GmailApp.getUserLabelByName("VOIDS");
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 message = messages[j];
var body = message.getPlainBody();
//email processing//
}
threads[i].removeLable(label);
}

Looking for a google apps script that permanently deletes from gmail trash

User is receiving a large volume of unwanted emails from a specific sender.
Blocking moves the email to spam, while filtering moves the email to trash. Both of these still expose the user to the emails if those folders are checked.
What I'm looking for is a script that will permanently delete emails from the specified email address either when the emails are received, or on a frequent schedule.
I have almost no familiarity with google scripts or js, the best I have as relates to code is some rudimentary vba.
Researching this issue brought me to using google apps as a potential solution as gmail does not provide any automated way to permanently delete email. Below is some code I found googling around, although I can't get very far with it due to my total lack of apps script knowledge.
function DeleteEmailByLabel(e) {personsemail#gmail.com}
var bannedLabel = 'BLOCKEDSENDER';
var deleteLabel = GmailApp.getUserLabelByName(bannedLabel);
if ( deleteLabel != null ) {personsemail#gmail.com}
var threads = deleteLabel.getThreads();
for (var i = 0; i < threads.length; i++) {
Gmail.Users.Messages.remove('me', threads[i].getId());
}
} else {
deleteLabel = GmailApp.createLabel(bannedLabel);
}
}
I expect the above code to run and remove email from my test account, from the trash folder. However instead I get this error. This looks like basic syntax stuff but I'm out of my league here.
Missing ; before statement. (line 1, file "filename")
Thanks in advance.
Before you could use this in the Apps Script, please note to do the following:
Create a filter in the user's Gmail account such that a specific & unique label is allocated to such emails (you can "mark them as read" or "send them to spam"; it wouldn't matter)
This function uses some of the advanced Gmail APIs and as such, require you to enable them from the script editor first, before running the script. To achieve this, go to:
Resources > Advanced Google Services... > Scroll all the way down to Gmail API > toggle the off button to on
function deleteEmails() {
var bannedLabel = 'BLOCKEDSENDER' // replace with the label name, as setup in filters
var deleteLabel = GmailApp.getUserLabelByName(bannedLabel);
if ( deleteLabel != null ) {
var threads = deleteLabel.getThreads();
for (var i=0; i<threads.length; i++) {
Gmail.Users.Threads.remove('me', threads[i].getId());
}
} else {
// do something
}
}

How to read all emails in gmail using google apps script

I'm trying to read ALL email in my gmail account - inbox, sent, draft, trash, emails with labels, archive, etc. I could live without the junk but I want everything else.
(all examples below use try {} catch {} to avoid errors with empty labels etc.)
I've tried
for (var i=StartLabel; i<=EndLabel; i++)
{
var label = labels[i].getName();
// get all messages, then join them into a single dimension array
var messages = GmailApp.getMessagesForThreads(GmailApp.search("label:" + label))
.reduce(function(a, b) {return a.concat(b);});
CountByLabels += messages.length;
}
That gives me everything in the labels (I think) but not the other stuff.
I tried other things, to get the inbox (to combine with the above) or all of the emails
var messages = GmailApp.getMessagesForThreads(GmailApp.getInboxThreads()).reduce(function(a, b) {return a.concat(b);});
CountInbox += messages.length;
but I only get about 549 results (GMail shows 5,478). If I add in the results from getPriorityInboxThreads I get 1,829 results.
I tried
// get all messages, then join them into a single dimension array
var messages = GmailApp.getMessagesForThreads(GmailApp.search("(is:unread OR is:read) in:anywhere")).reduce(function(a, b) {return a.concat(b);});
CountByLabels += messages.length;
I get 598 results.
I tried different search terms in the code directly above, eg:
is:unread = 528 results
is:read = 1,037 results
is:read OR is:unread = 599 results
None of them gave the right number, or even close, and incidentally if I try those search terms directly in gmail I get a totally different, and much higher, result for each - several thousand, or 'many'.
I don't think this is related to How to use Google App Scripts to retrieve Gmail emails in a customised way? as the numbers returned are not round numbers (eg 500).
I'm assuming that I can use getSpamThreads, getStarredThreads, getTrashThreads, getDraftMessages to get the relevant folders but until I understand why I'm only getting some emails from the inbox I don't trust those to give me everything.
Can anyone help?
Try this:
function allEmailsInLabels() {
var allLabels,i,j,L,L2,msgCount,theCount,threads,thisLabel;
msgCount = 0;
theCount = 0;
allLabels = GmailApp.getUserLabels();
L = allLabels.length;
for (i = 0; i < L; i++) {
Logger.log("label: " + allLabels[i].getName());
thisLabel = allLabels[i];
threads = thisLabel.getThreads();
//Logger.log('threads: ' + threads);
L2 = threads.length;
for (j = 0; j < L2; j++) {
msgCount = threads[j].getMessageCount();
//Logger.log('thread message count: ' + threads[j].getMessageCount());
// You could do something with threads[j] here like
// threads[j].moveToTrash();
theCount = theCount + msgCount;
};
};
//Logger.log('theCount: ' + theCount);
};
It first gets all the labels, then the threads, then the message count in each thread, and keeps a running count. You'll also need to get the messages in the inbox, that code doesn't include them. This is the sample code from the documentation that shows the basic concept:
// Log the subject lines of your Inbox
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
Logger.log(threads[i].getFirstMessageSubject());
}
I had the same question. Reading a little bit more in the reference in the Google Developers Website, I discovered, reading about the function moveToInbox, a Google sample that used the Search to get all e-mails that weren't in the Inbox (https://developers.google.com/apps-script/reference/gmail/gmail-thread#movetoinbox). I decided to combine this with the getInboxThreads and with these two, my code was shorter and found every e-mail that I had received (less spam and junk).
function getEmails() {
var generalThreads, inboxThreads;
inboxThreads = GmailApp.getInboxThreads();
generalThreads = GmailApp.search('-in:inbox');
}
Every single email that was in the folder "All mail" in the Gmail was in these two variables after this.
I don't know if this can help anyone, but surely helped me.
I know this is coming a bit delayed, but having had the same problem and looking at some of the solutions offered here, I wanted to offer up my own solution, which also uses the search function:
function getEmails() {
var allEmailThreads = GmailApp.search('label:all')
}
This actually filters for every email, regardless of the mailbox, and seems to me to be the simplest solution to the question.
This is not an answer to your problem (but is probably one of the reasons your total results returned don't agree with what you are seeing in gmail inbox) but highlights one of the problems I encountered when calling getPriorityInboxThreads() is that it ignores any thread that is not flagged as "important" in the primary inbox.
//returns 10 threads and 1st message for each thread
function getThreads(){
var ret = '';
var threads = GmailApp.getPriorityInboxThreads(0, 10);
for (var i = 0 ; i < threads.length; i++) {
var id = threads[i].getId();
var message = GmailApp.getMessageById(id);
ret += "subject: " + message.getSubject() +'\n';
Logger.log("subject: " + message.getSubject());
/*Edited this out as it doesn't return anything
//check for labels on this thread
var labels = threads[i].getLabels();
for (var j = 0; j < labels.length; j++) {
Logger.log(labels[j].getName());
} */
}
return ret;
}
"Important" is classed as a system flag and getPriorityInboxThreads() ignores any thread that is not flagged important....
I would like to select all threads in "Primary" inbox irrespective of being labelled as "important".
To test, simply change any thread in inbox to important or not etc.
After I published a video on how to get Gmail messages into a Google spreadsheet, I received a feedback from some viewers that they could only get a number of messages but others fail to be processed. Therefore, I did some research and found that the process of getting emails may fail and make the system unable to handle the huge amount of emails. This is mentioned in the Gmail API here:
https://developers.google.com/apps-script/reference/gmail/gmail-label#getthreads
The documentation suggests to use getThreads(start, max) where start and max are the limiting parameters.
You may view the video and download the full code from YouTube and GitHub:
https://youtu.be/gdgCVqtcIw4

Google Script Quota Issues: Gmail Read

I'm having a bit of trouble with my google script code. I'm trying to make a script that will automatically take any email that is sent with 'Events' in the subject and parse the text to add it to the calendar. I have a filter that will add the email to the label 'Events', then remove the label.
The script is working fine and is posted below. I have it triggering every minute. However, every day I get a huge failure notification email that I've exceeded the quota for gmail reads on line 4 [GmailApp.getUserLabelbyName]. I tried googling and I couldn't find more specifics.
So, according to the quota website I have a limit of 10,000 reads per day. This has been failing with no emails at all in the 'Events' bin, so no actual emails appear to be read. The calendar should be accessing it once per minute, i.e. 1,440 times a day.
So why am I getting the quota failure for gmail read? Does 'gmail reads' mean accesses to gmail (getting the label variable) or reading email bodies (getThreads) or both?
Any help would be greatly appreciated. Thanks!
function MakeEvents() {
var label = GmailApp.getUserLabelByName("Events");
if (label) {
var threads = label.getThreads();
for (var x in threads) {
var messages = threads[x].getMessages();
for (var y in messages) {
var myHTMLContent = messages[y].getBody();
textContent=getTextFromNode(Xml.parse(myHTMLContent, true).getElement());
CalendarApp.getDefaultCalendar().createEventFromDescription(textContent);
}
threads[x].removeLabel(label);
}
}
}
function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
default: return '';
}
}