├── README.md ├── append_too_old_labels.gs ├── auto_expire.gs ├── expire_promotions_tab.gs ├── log_inbox_count.gs └── log_oldest_email_age.gs /README.md: -------------------------------------------------------------------------------- 1 | # google-apps-scripts 2 | 3 | A collection of my Google Apps Script code, primarily for automating Gmail. 4 | 5 | * **append_too_old_labels.gs** - add a label to old email threads in your inbox indicating how many days old they are. 6 | * **auto_expire.gs** - automatically expire emails so they don't spend too long in your inbox. 7 | * **expire_promotions_tab.gs** - automatically expire all emails which Gmail categorizes into the "Promotions" tab (combined with auto_expire.gs). 8 | * **log_inbox_count.gs** - log the number of threads in your inbox. 9 | * **log_oldest_email_age.gs** - log the age of the oldest message thread in your inbox. 10 | 11 | ## Installation 12 | 13 | 1. Visit https://script.google.com/ and create a script for "Blank Project". 14 | 1. Paste the file in. 15 | 1. Follow additional instructions at the top of the file, e.g. to set configuration variables. 16 | 1. Click the name "Untited project" at the top of the screen and change it to something descriptive of what the script does. 17 | 1. In the menu at the top of the screen, go to Resources -> Current project's triggers. This is where you will set your script to run regularly. The instructions at the top of the file should indicate which function and how often. 18 | 1. Profit! 19 | -------------------------------------------------------------------------------- /append_too_old_labels.gs: -------------------------------------------------------------------------------- 1 | // Add a label to old email threads in your inbox indicating how many days old 2 | // they are. 3 | // 4 | // 1. Set MIN_AGE_TO_APPEND_LABEL, LABEL_PREFIX, and DELETE_UNUSED_LABELS at the 5 | // top of the script. 6 | // If LABEL_PREFIX is 'd', threads will get labels like 'd21'. This script 7 | // will also *remove* labels that look like (LABEL_PREFIX + a number) when 8 | // they no longer apply to a message, so choose something that isn't used for 9 | // anything else. 10 | // 2. Test the script by running the appendTooOldLabels function. 11 | // 3. (Optional) Go to Gmail and customize the colors of the relevant labels. 12 | // You may need to add some labels since the function will create them only 13 | // when they are needed. 14 | // 4. Set appendTooOldLabels to run daily, just after midnight. 15 | 16 | var MIN_AGE_TO_APPEND_LABEL = 21; 17 | var LABEL_PREFIX = 'd'; 18 | 19 | // Set to true if you don't want a label like d8 in your sidebar when there are 20 | // no emails to which it applies. The downside is that you'll lose your label 21 | // preferences (color, show in label list, etc.). 22 | var DELETE_UNUSED_LABELS = false; 23 | 24 | var PAGE_SIZE = 50; 25 | 26 | function appendTooOldLabels() { 27 | var now = new Date(); 28 | 29 | var start = 0; 30 | var threads; 31 | 32 | var existingLabels = unlabelMessages(); 33 | var usedLabels = {}; 34 | 35 | do { 36 | threads = GmailApp.getInboxThreads(start, PAGE_SIZE); 37 | 38 | threads.forEach(function(thread) { 39 | age = dateDiffInDays(thread.getLastMessageDate(), now); 40 | if(age >= MIN_AGE_TO_APPEND_LABEL) { 41 | addAgeLabel(thread, age); 42 | usedLabels[LABEL_PREFIX + age] = true; 43 | } 44 | }); 45 | 46 | start += PAGE_SIZE; 47 | Utilities.sleep(1000); 48 | } while(threads.length > 0); 49 | 50 | if (DELETE_UNUSED_LABELS) { 51 | removeUnusedAgeLabels(existingLabels, usedLabels); 52 | } 53 | } 54 | 55 | function unlabelMessages() { 56 | var ageLabelRe = new RegExp('^' + LABEL_PREFIX + '\\d+$'); 57 | var labelNames = []; 58 | GmailApp.getUserLabels().forEach(function(label) { 59 | if(label.getName().match(ageLabelRe)) { 60 | labelNames.push(label.getName()); 61 | label.removeFromThreads(label.getThreads()); 62 | Utilities.sleep(1000); 63 | } 64 | }); 65 | return labelNames; 66 | } 67 | 68 | function addAgeLabel(thread, age) { 69 | var labelName = LABEL_PREFIX + age; 70 | var label = GmailApp.getUserLabelByName(labelName); 71 | if(label === null) { 72 | label = GmailApp.createLabel(labelName); 73 | } 74 | label.addToThread(thread); 75 | } 76 | 77 | function removeUnusedAgeLabels(existing, used) { 78 | existing.forEach(function(labelName) { 79 | if (used[labelName] === undefined) { 80 | GmailApp.getUserLabelByName(labelName).deleteLabel(); 81 | } 82 | }); 83 | } 84 | 85 | function dateDiffInDays(d1, d2) { 86 | // compare dates only, ignore time of day 87 | return Math.round((datetimeToDate(d2) - datetimeToDate(d1)) / (1000 * 60 * 60 * 24)); 88 | } 89 | 90 | function datetimeToDate(d) { 91 | return new Date(1990 + d.getYear(), d.getMonth(), d.getDate()); 92 | } 93 | -------------------------------------------------------------------------------- /auto_expire.gs: -------------------------------------------------------------------------------- 1 | // Automatically expire emails in your inbox. Each day, any email with a label 2 | // beginning with "x" has its label updated to take one step closer to "x0" 3 | // ("x4" becomes "x3", etc.). An email with label "x0" is archived. 4 | // 5 | // 1. Set MAX_DAYS at the top of the script to the highest number label you 6 | // want to create. 7 | // 2. Run the setup() function to create the labels. 8 | // (Optional) Go to Gmail and customize the colors of those labels. 9 | // 3. Set the stepExpiration function to run once a day, at the end of the day. 10 | // 4. Create Gmail filters to automatically assign a label like x4 or x2 11 | // (depending on how fast of an expiration you want) to emails with 12 | // certain senders or subjects. 13 | 14 | var MAX_DAYS = 6; 15 | 16 | function setup() { 17 | for(var i = 0; i <= MAX_DAYS; i++) { 18 | GmailApp.createLabel("x" + i); 19 | } 20 | } 21 | 22 | function stepExpiration() { 23 | var threads; 24 | 25 | for(var i = 0; i <= MAX_DAYS; i++) { 26 | threads = null; 27 | 28 | while(!threads || threads.length == 100) { 29 | threads = GmailApp.getUserLabelByName("x" + i).getThreads(0, 100); 30 | 31 | if(threads.length > 0) { 32 | GmailApp.getUserLabelByName("x" + i).removeFromThreads(threads); 33 | 34 | if(i == 0) { 35 | GmailApp.moveThreadsToArchive(threads); 36 | } else { 37 | GmailApp.getUserLabelByName("x" + (i - 1)).addToThreads(threads); 38 | } 39 | } 40 | 41 | Utilities.sleep(1000); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /expire_promotions_tab.gs: -------------------------------------------------------------------------------- 1 | // Automatically expire all emails which Gmail places into the "Promotions" tab. 2 | // (credit: @beaugunderson) 3 | // 4 | // This relies on auto_expire.gs. This separate script is necessary because you 5 | // can't create a filter for things that Gmail categorizes into the "Promotions" 6 | // tab, unfortunately. 7 | // 8 | // 1. If you haven't already done so, set up auto_expire.gs. 9 | // 2. Set PROMOTION_DAYS to the number of days that you want the emails to stay 10 | // in the "Promotions" tab before expiring. 11 | // 3. Set addPromotionsExpiration to run every 15 minutes. 12 | 13 | var PROMOTION_DAYS = 7; 14 | 15 | function addPromotionsExpiration() { 16 | var filters = [ 17 | 'label:Promotions', 18 | 'in:inbox' 19 | ]; 20 | 21 | for (var i = 0; i <= PROMOTION_DAYS; i++) { 22 | filters.push('-label:x' + i); 23 | } 24 | 25 | var threads = GmailApp.search(filters.join(' ')); 26 | 27 | GmailApp.getUserLabelByName('x' + PROMOTION_DAYS).addToThreads(threads); 28 | } 29 | -------------------------------------------------------------------------------- /log_inbox_count.gs: -------------------------------------------------------------------------------- 1 | // Log the number of threads in your inbox. 2 | // 3 | // 1. Create a new spreadsheet or add a new sheet to an existing spreadsheet 4 | // where you want to log the data. 5 | // 2. Add column headings, "Date" and "Count", to the first row of that sheet. 6 | // 3. Set SPREADSHEET_URL and SHEET_NAME to that spreadsheet and sheet. 7 | // 4. Set the logInboxCount function to run hourly or daily, depending on how 8 | // often you want to gather this data. 9 | 10 | var SPREADSHEET_URL = 'put your google spreadsheet url here (ends in /edit)'; 11 | var SHEET_NAME = 'put the name of the sheet here (e.g. Sheet1)'; 12 | 13 | var PAGE_SIZE = 50; 14 | 15 | function logInboxCount() { 16 | var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL); 17 | var sheet = ss.getSheetByName(SHEET_NAME); 18 | 19 | var count = 0; 20 | var start = 0; 21 | var threads; 22 | 23 | do { 24 | threads = GmailApp.getInboxThreads(start, PAGE_SIZE); 25 | count += threads.length; 26 | 27 | start += PAGE_SIZE; 28 | Utilities.sleep(1000); 29 | } while(threads.length > 0); 30 | 31 | // if the sheet is full, add a new batch of rows 32 | if(sheet.getLastRow() == sheet.getMaxRows()) { 33 | sheet.insertRowsAfter(sheet.getMaxRows(), 100); 34 | } 35 | 36 | sheet.getRange(sheet.getLastRow() + 1, 1, 1, 2).setValues([[new Date(), count]]); 37 | } 38 | -------------------------------------------------------------------------------- /log_oldest_email_age.gs: -------------------------------------------------------------------------------- 1 | // Log the age of the oldest message thread in your inbox (only if it has 2 | // changed since the last time it was logged). 3 | // 4 | // 1. Create a new spreadsheet or add a new sheet to an existing spreadsheet 5 | // where you want to log the data. 6 | // 2. Add column headings, "Date" and "Oldest Email", to the first row of that 7 | // sheet. 8 | // 3. Set SPREADSHEET_URL and SHEET_NAME to that spreadsheet and sheet. 9 | // 4 Set logOldestEmailAge to run every 5 minutes. 10 | // 5. (Optional) Use Zapier to send this data to a Beeminder "do less" goal to 11 | // force yourself to deal with emails before they get too old. 12 | 13 | var SPREADSHEET_URL = 'put your google spreadsheet url here (ends in /edit)'; 14 | var SHEET_NAME = 'put the name of the sheet here (e.g. Sheet1)'; 15 | 16 | var PAGE_SIZE = 50; 17 | 18 | function logOldestEmailAge() { 19 | var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL); 20 | var sheet = ss.getSheetByName(SHEET_NAME); 21 | 22 | var now = new Date(); 23 | var oldest = now; 24 | 25 | var start = 0; 26 | var threads; 27 | 28 | do { 29 | threads = GmailApp.getInboxThreads(start, PAGE_SIZE); 30 | 31 | threads.forEach(function(thread) { 32 | oldest = thread.getLastMessageDate() < oldest ? thread.getLastMessageDate() : oldest; 33 | }); 34 | 35 | start += PAGE_SIZE; 36 | Utilities.sleep(1000); 37 | } while(threads.length > 0); 38 | 39 | var ageOfOldest = dateDiffInDays(oldest, now); 40 | var lastValueLogged = sheet.getRange(sheet.getLastRow(), 2).getValue(); 41 | 42 | if(ageOfOldest !== lastValueLogged) { 43 | 44 | // if the sheet is full, add a new batch of rows 45 | if(sheet.getLastRow() === sheet.getMaxRows()) { 46 | sheet.insertRowsAfter(sheet.getMaxRows(), 100); 47 | } 48 | 49 | sheet.getRange(sheet.getLastRow() + 1, 1, 1, 2).setValues( 50 | [[now, ageOfOldest]] 51 | ); 52 | 53 | } 54 | } 55 | 56 | function dateDiffInDays(d1, d2) { 57 | // compare dates only, ignore time of day 58 | return Math.round((datetimeToDate(d2) - datetimeToDate(d1)) / (1000 * 60 * 60 * 24)); 59 | } 60 | 61 | function datetimeToDate(d) { 62 | return new Date(1990 + d.getYear(), d.getMonth(), d.getDate()); 63 | } 64 | --------------------------------------------------------------------------------