Removing label from Gmail email after X days using Google Apps Script - google-apps-script

I created a Google Apps Script Code.gs as follows to remove the Gmail label from every thread that is older than X days and labeled Y.
function archiveYThreads() {
// Every thread, older than two days, and labeled "Unread Feeds".
var threads = GmailApp.search('label:"Unread Feeds" older_than:2d');
for (var i = 0; i < threads.length; i++) {
threads[i].removeLabel("Unread Feeds");
}
}
According to the documentation, the function removeLabel exists. Alternatively, I found some sources that use deleteLabel. However, with both I get the error that both functions do not exist, after having set a time-based trigger:
Can anybody please help me detecting why the function does not work?

You have to supply an object of type GmailLabel as the argument to removeLabel() method. Try this snippet.
function archiveYThreads() {
var label = GmailApp.getUserLabelByName("Unread Feeds");
var threads = GmailApp.search('label:"Unread Feeds" older_than:2d');
for (var i = 0; i < threads.length; i++) {
threads[i].removeLabel(label);
}
}

Related

Is there a way to set up a trigger for when I receive an email? [duplicate]

I've been reading through gmail addons. They have contextual triggers that trigger when you open an email.
Is it possible to trigger a service when an email is received by me? Best I can find is unconditional but that only triggers when the email is opened.
You can't create a trigger for every email, however you can do something similar as described in this answer.
For example you can:
Set up a filter that puts a special label on incoming emails that you want to process.
Set up a reoccurring script that runs every 10 minutes, or even every minute. In the script, you can pull all of the emails that have the given label, and process them accordingly, removing the label when you are done.
function processEmails() {
var label = GmailApp.getUserLabelByName("Need To Process");
var threads = label.getThreads();
for (var i = threads.length - 1; i >= 0; i--) {
//Process them in the order received
threads[i].removeLabel(label).refresh();
}
}
You can then set this on a time based trigger to have it run as often as you would like.
If you want to keep track of the emails you have processed, you can create another "processed" label and add that to the message when you are done processing.
I had a little trouble with getting the labels right so I'm including code to log your labels. I modified user3312395's code also to add new label also.
Thanks for the original answer too!
function emailTrigger() {
var label = GmailApp.getUserLabelByName('Name of Label to Process');
var newLabel = GmailApp.getUserLabelByName('New Label Name');
if(label != null){
var threads = label.getThreads();
for (var i=0; i<threads.length; i++) {
//Process them in the order received
threads[i].removeLabel(label);
threads[i].addLabel(newLabel);
//run whatever else here
}
}
}
function getLabels(){
var labels = GmailApp.getUserLabels();
for(i=0; i<labels.length; i++){
Logger.log(labels[i].getName());
}
}
Yes, you can trigger a function for every new email!
Just use the search query newer_than:1h. Have your trigger run every 10 minutes for example. Then you will essentially be running logic for every new email (with up to 10 minutes delay, which is probably fine).
var TRIGGER_NAME = 'handleNewEmails'
// Maximum number of threads to process per run.
var PAGE_SIZE = 150
var INTERVAL = 10
function Install() {
// First run 2 mins after install
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased()
.at(new Date(new Date().getTime() + 1000 * 60 * 2))
.create()
// Run every 10 minutes there after
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased().everyMinutes(INTERVAL).create()
}
function Uninstall() {
var triggers = ScriptApp.getProjectTriggers()
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === TRIGGER_NAME) ScriptApp.deleteTrigger(triggers[i])
}
}
function handleNewEmails() {
var threads = GmailApp.search("newer_than:1h", 0, PAGE_SIZE)
for (var i = 0; i < threads.length; i++) {
var thread = threads[i]
// Do something with the thread.
}
}
Actually, they have somewhat complex pub/sub service that requires setting up OAuth authentication. With this service you'll must be able to get push notifications. But I also think its easier to set up a trigger to run every 10 or even 1 minute.

Google gmail script that triggers on incoming email

I've been reading through gmail addons. They have contextual triggers that trigger when you open an email.
Is it possible to trigger a service when an email is received by me? Best I can find is unconditional but that only triggers when the email is opened.
You can't create a trigger for every email, however you can do something similar as described in this answer.
For example you can:
Set up a filter that puts a special label on incoming emails that you want to process.
Set up a reoccurring script that runs every 10 minutes, or even every minute. In the script, you can pull all of the emails that have the given label, and process them accordingly, removing the label when you are done.
function processEmails() {
var label = GmailApp.getUserLabelByName("Need To Process");
var threads = label.getThreads();
for (var i = threads.length - 1; i >= 0; i--) {
//Process them in the order received
threads[i].removeLabel(label).refresh();
}
}
You can then set this on a time based trigger to have it run as often as you would like.
If you want to keep track of the emails you have processed, you can create another "processed" label and add that to the message when you are done processing.
I had a little trouble with getting the labels right so I'm including code to log your labels. I modified user3312395's code also to add new label also.
Thanks for the original answer too!
function emailTrigger() {
var label = GmailApp.getUserLabelByName('Name of Label to Process');
var newLabel = GmailApp.getUserLabelByName('New Label Name');
if(label != null){
var threads = label.getThreads();
for (var i=0; i<threads.length; i++) {
//Process them in the order received
threads[i].removeLabel(label);
threads[i].addLabel(newLabel);
//run whatever else here
}
}
}
function getLabels(){
var labels = GmailApp.getUserLabels();
for(i=0; i<labels.length; i++){
Logger.log(labels[i].getName());
}
}
Yes, you can trigger a function for every new email!
Just use the search query newer_than:1h. Have your trigger run every 10 minutes for example. Then you will essentially be running logic for every new email (with up to 10 minutes delay, which is probably fine).
var TRIGGER_NAME = 'handleNewEmails'
// Maximum number of threads to process per run.
var PAGE_SIZE = 150
var INTERVAL = 10
function Install() {
// First run 2 mins after install
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased()
.at(new Date(new Date().getTime() + 1000 * 60 * 2))
.create()
// Run every 10 minutes there after
ScriptApp.newTrigger(TRIGGER_NAME)
.timeBased().everyMinutes(INTERVAL).create()
}
function Uninstall() {
var triggers = ScriptApp.getProjectTriggers()
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === TRIGGER_NAME) ScriptApp.deleteTrigger(triggers[i])
}
}
function handleNewEmails() {
var threads = GmailApp.search("newer_than:1h", 0, PAGE_SIZE)
for (var i = 0; i < threads.length; i++) {
var thread = threads[i]
// Do something with the thread.
}
}
Actually, they have somewhat complex pub/sub service that requires setting up OAuth authentication. With this service you'll must be able to get push notifications. But I also think its easier to set up a trigger to run every 10 or even 1 minute.

Google Apps substring from null

I put my first Google Apps Script together to write emails to a spreadsheet. It works fine, except of the substring method I would like to use to shorten the message body. The script engine returns "cannot call substring from null […]". I found this thread (google apps script TypeError: Cannot call method "substring" of undefined) but the solution didn't help – or I didn't understand it which is about as likely.
Here's my script.
function labelToSpreadsheet() {
var threads = GmailApp.getUserLabelByName('newaddress').getThreads();
var spreadsheet = SpreadsheetApp.openById("onehellofanID")
var sheet = spreadsheet.getSheets()[0];
Logger.log (spreadsheet.getName());
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var shortendContent = messages[j].getPlainBody().substring(0, 500);
sheet.appendRow([messages[j].getSubject(), messages[j].getFrom(), messages[j].getReplyTo(), messages[j].getDate(), shortendContent]);
}
}
};
This was driving me nuts, as there was no reason your code wouldn't work, and I was getting the same error. I narrowed it down to the 'getPlainBody()' was returning 'null', but couldn't figure out why this was the case even when I used GMails own example.
I was almost going to call it a bug when I realized that what was happening was that some messages were returning nothing in the body. Specifically, some companies send out newsletters that aren't text content at all, but in fact are images with their content inside (Which was the case with the first message in the test label I had, thus driving me bonkers).
So, the issue here is that the label you're running this under has some messages where the content is only an image, no text whatsoever (Or potentially, is just completely blank), thus 'getPlainBody()' returns 'There's nothing there'(Null) and you can't get a substring of nothing.
A simple 'if' statement actually handles this error really well, as you can then tell the script to write to the sheet 'The content of this message was an image' (Or whatever you want).
This slightly modified version of your code works for me:
function labelToSpreadsheet() {
var threads = GmailApp.getUserLabelByName(LABELNAME).getThreads();
var spreadsheet = SpreadsheetApp.openById(SHEETID);
var sheet = spreadsheet.getSheets()[0];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
if(messages[j].getPlainBody() == null){
var shortendContent = 'This message was an image';
}else{
var shortendContent = messages[j].getPlainBody().substring(0, 500);
};
sheet.appendRow([messages[j].getSubject(), messages[j].getFrom(), messages[j].getReplyTo(), messages[j].getDate(), shortendContent]);
}
}
};
I'm giving myself a gold star for this one, it was annoying to figure out.

reply time between threads [google apps script]

I want to develop a script in GAS to get the reply time of all of my threads in Gmail in a specific period. The example script below seems to be a way, but im not sure on how to proceed.
function processInbox() {
// get all threads in inbox
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// iterate over each message
for (var j = 0; j < messages.length; j++) {
// log message subject
Logger.log(messages[j].getSubject());
}
}
};
Maybe use:
Google Documentation - getDate() GmailMessage Class
When you say you want to "get" the information, how do you want to get it? Be sent an email? Store it in a spreadsheet? Record it in a .csv file?

Get Gmail categories

I used to have a working apps script that deleted old promotional emails in my Gmail account.
It used the code
var label = GmailApp.getUserLabelByName("Promotions");
to get the label and then it iterated through label.getThreads() to decide whether each thread was old enough to delete.
However, Google have now changed Gmail so the auto categorisations are now under the Categories section in the UI, rather than within the list of labels so the above now returns null.
How can I fix my code to retrieve the Promotions category? I have tried Categories/Promotions too but it also comes up null.
Gmail categories can easily be searched.
Here is a small code that looks for every promotion mail. The result is an array of threads, you can add Label to each of them so that your old script will be happy again ;-)
var threads = GmailApp.search('category:promotions');// check the category Gmail added to the thread
documentation here
Here is a script I use to delete old promotional emails as well as some other categories and custom labels.
function auto_delete_email(){
delete_Label ("Cameras",30);
delete_Label ("Travel",365);
delete_Category ("Social",90);
delete_Category ("Finance",365*3);
delete_Category ("Forums",90);
delete_Category ("Promos",365*3);
}
function delete_Label(mailLabel,delayDays) {
var label = GmailApp.getUserLabelByName(mailLabel);
if (!label) {return false;}
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()-delayDays);
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
if (threads[i].getLastMessageDate()<maxDate){
threads[i].moveToTrash();
}
}
function delete_Category(mailCategory,delayDays) {
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()-delayDays);
var threads = GmailApp.search('category:' + mailCategory);
for (var i = 0; i < threads.length; i++) {
if (threads[i].getLastMessageDate()<maxDate){
threads[i].moveToTrash();
}
}
}
You can also expand the search criteria to use (d, m, y) like "older_than:1y" which mimics the search box functionality in the Gmail app. This may be helpful as I've had significant issues getting the date comparison to work smoothly.
For example:
function delete_old_Category() {
var maxDate = new Date();
maxDate.setDate(maxDate.getDate()- 180);
var threads = GmailApp.search("category:promos older_than:6m",0, 100);
for (var i = 0; i < threads.length; i++) {
threads[i].moveToTrash(); {
}
}
}