Last active
March 19, 2018 13:41
-
-
Save antelio/797f2eea0d6469625fd2 to your computer and use it in GitHub Desktop.
Gmail Snooze V1.6 - 2015-06-04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // --------------------------------------------------------------------------------------------------------------------------------------------------- | |
| // The MIT License (MIT) | |
| // | |
| // Copyright (c) 2015 Iain Brown - http://www.littlebluemonkey.com/gmail-snooze-without-mailboxapp/ | |
| // | |
| // Inspired by http://gmailblog.blogspot.co.nz/2011/07/gmail-snooze-with-apps-script.html | |
| // | |
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| // of this software and associated documentation files (the "Software"), to deal | |
| // in the Software without restriction, including without limitation the rights | |
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| // copies of the Software, and to permit persons to whom the Software is | |
| // furnished to do so, subject to the following conditions: | |
| // | |
| // The above copyright notice and this permission notice shall be included in all | |
| // copies or substantial portions of the Software. | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| // SOFTWARE. | |
| // ====================================================================== | |
| // Instructions | |
| // ====================================================================== | |
| // | |
| // 1. I would recommend making a copy of this script so that you can edit your settings, and maintain ownership of the code. | |
| // This is done using the menu above: File->Make A Copy | |
| // | |
| // 2. Edit these user configurable settings - or leave them if you think they're ok. | |
| var MARK_UNREAD = true; // When true, marks thread as unread when moving it back to the inbox | |
| var MARK_MESSAGE_UNREAD_ONLY = true; // When true, only marks the most recent message as unread | |
| var ADD_UNSNOOZED_LABEL = true; // Adds the unsnoozed label when moving back to the inbox | |
| var ADD_SNOOZE_ERROR_LABEL = true; // If an invalid snooze label is used, labels thread as invalid when returning to inbox. | |
| var SNOOZE_LABEL = "* Snooze"; // Prefixing it with * puts it at the top of the list. | |
| var UNSNOOZE_LABEL = "* Unsnoozed"; // Prefixing it with * puts it at the top of the list. | |
| var SNOOZE_ERROR_LABEL = "Snooze Error!"; | |
| var TIME_DAY_STARTS = "0700"; // If you want emails to be unsnoozed at say 8am, change to "0800" | |
| var REMOVE_UNSNOOZE_LABEL = false; // If you want unsnooze label to be removed once message is no longer in Inbox | |
| // 3. Select Run->Setup from the menu above. | |
| // | |
| // 4. If prompted to authorise this script to access Gmail and Calendar (which is used to determine your preferred timezone) | |
| // then authorise the script until you see the text "Now you can run the script." - THEN REPEAT STEP 3 to complete the setup. | |
| // | |
| // 5. You're now good to go - when you go to Gmail, you should now have Snooze labels that you can use to snooze in various ways. | |
| // | |
| // | |
| // ------------------------------------------------------------------------------------------------------------------------ | |
| // | |
| // For more detailed instructions, and examples, visit: http://www.littlebluemonkey.com/gmail-snooze-without-mailboxapp/ | |
| // | |
| // ------------------------------------------------------------------------------------------------------------------------ | |
| // | |
| // Release Notes: 03/07/2013 1.2 - Fixed buy where certain mmddyy dates were resulting in 'Snooze Error!' labels being applied | |
| // 18/08/2013 1.3 - Added Next Week/Next Month functionality that unsnoozes on following Monday/1st of Month | |
| // 11/03/2014 1.4 - Added time for new days to start | |
| // 14/01/2015 1.5 - Replacing deprecated API's | |
| // 04/06/2015 1.6 - Optionally remove Unsnoozed label when no longer in Inbox | |
| // ------------------------------------------------------------------------------------------------------------------------ | |
| // ====================================================================== | |
| // Code - Don't proceed any further unless you're a trained professional. | |
| // ====================================================================== | |
| // -------------------------------------------------------------------------- | |
| // Stuff that you really shouldn't be touching unless you want to break stuff. | |
| // -------------------------------------------------------------------------- | |
| var KEY_TOMORROW_DATE = "tomorrowDate"; | |
| var KEY_CURRENT_DAY = "currentDay"; | |
| var MONDAY_LABEL = "1 - Monday"; | |
| var TUESDAY_LABEL = "2 - Tuesday"; | |
| var WEDNESDAY_LABEL = "3 - Wednesday"; | |
| var THURSDAY_LABEL = "4 - Thursday"; | |
| var FRIDAY_LABEL = "5 - Friday"; | |
| var SATURDAY_LABEL = "6 - Saturday"; | |
| var SUNDAY_LABEL = "7 - Sunday"; | |
| var snoozeErrorLabel = null; | |
| var unsnoozeLabel = null; | |
| // -------------------------------------------------------------------------- | |
| // Setup function to add labels, initialise properties and set script trigger. | |
| // -------------------------------------------------------------------------- | |
| function setup() { | |
| GmailApp.createLabel(SNOOZE_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/0 - Tomorrow"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + MONDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + TUESDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + WEDNESDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + THURSDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + FRIDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + SATURDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/" + SUNDAY_LABEL); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - next_week"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - next_month"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - time_hhmm"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - time_hhmm/1200"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - time_hhmm/1700"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/8 - time_hhmm/2000"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/9 - date_ddmmyy"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/9 - date_mmddyy"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/9 - date_ddmmyy/280219"); | |
| GmailApp.createLabel(SNOOZE_LABEL + "/9 - date_mmddyy/022819"); | |
| if (ADD_UNSNOOZED_LABEL) { | |
| GmailApp.createLabel(UNSNOOZE_LABEL); | |
| } | |
| initialiseProperty(KEY_TOMORROW_DATE, getCurrentIsoDate()); | |
| initialiseProperty(KEY_CURRENT_DAY, getCurrentDay()); | |
| ScriptApp.newTrigger("moveSnoozes").timeBased().everyMinutes(1).create(); | |
| } | |
| // ------------------------------------------------------------------------ | |
| // The main script that does all the good stuff - triggered every 1 minute: | |
| // ------------------------------------------------------------------------ | |
| function moveSnoozes() { | |
| var oldLabel, newLabel, page; | |
| var today = getCurrentDay(); | |
| var todayIso = getCurrentIsoDate(); | |
| var now = getCurrentIsoDateAndTime(); | |
| var newDay = isNewDay(today,TIME_DAY_STARTS); | |
| var snoozeLength = SNOOZE_LABEL.length; | |
| var labelName = ""; | |
| var labels = GmailApp.getUserLabels(); | |
| for (var i = 0; i < labels.length; i++) { | |
| labelName = labels[i].getName(); | |
| if (labelName.length >= snoozeLength) { | |
| if (labelName.substr(0,snoozeLength) == SNOOZE_LABEL) { | |
| if (isDayLabel(labelName)) { | |
| if (newDay && labelName.substr(snoozeLength + 5) === today) { | |
| processLabel(labels[i]); | |
| } | |
| } | |
| else if(labelName.substr(snoozeLength) == "/0 - Tomorrow") { | |
| if (newDay && tomorrowCanBeProcessed(todayIso)) { | |
| processLabel(labels[i]); | |
| PropertiesService.getUserProperties().setProperty(KEY_TOMORROW_DATE, todayIso); | |
| } | |
| } | |
| else if(labelName.substr(snoozeLength) == "/8 - next_week") { | |
| if (newDay && nextWeekCanBeProcessed(today)) { | |
| processLabel(labels[i]); | |
| } | |
| } | |
| else if(labelName.substr(snoozeLength) == "/8 - next_month") { | |
| if (newDay && nextMonthCanBeProcessed(todayIso)) { | |
| processLabel(labels[i]); | |
| } | |
| } | |
| else if(isValidTimeLabel(labelName,snoozeLength)) { | |
| var time = getTimeFromLabel(labelName,snoozeLength); | |
| if (timeCanBeProcessed(time,now)) { | |
| processLabel(labels[i]); | |
| PropertiesService.getUserProperties().setProperty("Time:"+time,now.substr(0,10)); | |
| } | |
| } | |
| else if(isValidDDMMYYLabel(labelName,snoozeLength)) { | |
| if (newDay && dateCanBeProcessed(getDateFromDDMMYYLabel(labelName,snoozeLength),todayIso)) { | |
| processLabel(labels[i]); | |
| GmailApp.deleteLabel(labels[i]); | |
| } | |
| } | |
| else if(isValidMMDDYYLabel(labelName,snoozeLength)) { | |
| if (newDay && dateCanBeProcessed(getDateFromMMDDYYLabel(labelName,snoozeLength),todayIso)) { | |
| processLabel(labels[i]); | |
| GmailApp.deleteLabel(labels[i]); | |
| } | |
| } | |
| // If there are any "Snooze" type labels that aren't what we're expecting | |
| // then flag them in error and move back to the inbox: | |
| else { | |
| processInvalidLabel(labels[i]); | |
| } | |
| } | |
| } | |
| } | |
| if (newDay) { | |
| PropertiesService.getUserProperties().setProperty(KEY_CURRENT_DAY, today); | |
| } | |
| if (REMOVE_UNSNOOZE_LABEL == true) { | |
| removeUnsnoozedLabels(); | |
| } | |
| return; | |
| } | |
| function removeUnsnoozedLabels() { | |
| var query = "(!label:inbox AND label:"+UNSNOOZE_LABEL.replace(/ /g, "-")+") " | |
| var threads = GmailApp.search(query); | |
| if (threads.length == 0) { | |
| return; | |
| } | |
| var label = GmailApp.getUserLabelByName(UNSNOOZE_LABEL) | |
| for (var i = 0; i<threads.length;i++) { | |
| threads[i].removeLabel(label); | |
| } | |
| } | |
| function processLabel(label) { | |
| var page = null; | |
| // Get threads in "pages" of 100 at a time | |
| while(!page || page.length == 100) { | |
| page = label.getThreads(0, 100); | |
| if (page.length > 0) { | |
| for (var i =0;i<page.length;i++) { | |
| if (MARK_UNREAD) { | |
| if (MARK_MESSAGE_UNREAD_ONLY) { | |
| var msgs = page[i].getMessages(); | |
| msgs[msgs.length-1].markUnread(); | |
| } | |
| else { | |
| page[i].markUnread(); | |
| } | |
| } | |
| page[i].moveToInbox(); | |
| page[i].removeLabel(label); | |
| if (ADD_UNSNOOZED_LABEL) { | |
| var unsnooze = getUnsnoozeLabel(); | |
| if (unsnooze != null) { | |
| page[i].addLabel(unsnooze); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| function processInvalidLabel(label) { | |
| var page = null; | |
| // Get threads in "pages" of 100 at a time | |
| while(!page || page.length == 100) { | |
| page = label.getThreads(0, 100); | |
| if (page.length > 0) { | |
| for (var i =0;i<page.length;i++) { | |
| page[i].markUnread(); | |
| page[i].moveToInbox(); | |
| page[i].removeLabel(label); | |
| if (ADD_SNOOZE_ERROR_LABEL) { | |
| var snoozeError = getSnoozeErrorLabel(); | |
| if (snoozeError != null) { | |
| page[i].addLabel(snoozeError); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return; | |
| } | |
| function tomorrowCanBeProcessed(newIsoDate) { | |
| var oldDate = PropertiesService.getUserProperties().getProperty(KEY_TOMORROW_DATE); | |
| if (oldDate !== newIsoDate) { | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| function nextWeekCanBeProcessed(newDay) { | |
| if (newDay === "Monday") { | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| function nextMonthCanBeProcessed(newIsoDate) { | |
| if (newIsoDate.substring(8) === "01") { | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| function timeCanBeProcessed(time,now) { | |
| if (time !== "") { | |
| var triggerDateAndTime = now.substr(0,10) + "-" + time; | |
| var processedDate = PropertiesService.getUserProperties().getProperty("Time:"+time); | |
| if (processedDate === null) { | |
| if (now > triggerDateAndTime) { | |
| processedDate = now.substr(0,10); | |
| } | |
| else { | |
| processedDate = "0001-01-01"; | |
| } | |
| PropertiesService.getUserProperties().setProperty("Time:"+time, processedDate); | |
| } | |
| if (now >= triggerDateAndTime) { | |
| if (processedDate === null || processedDate === "" || processedDate < getCurrentIsoDate()) { | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| function dateCanBeProcessed(theDate,today) { | |
| if (today >= theDate) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| function getTimeFromLabel(labelName,snoozeLength) { | |
| var labelLength = labelName.length; | |
| var timeLength = labelLength - (snoozeLength+15); | |
| var time = ""; | |
| if ( labelLength == snoozeLength + 18 || labelLength == snoozeLength + 19) { | |
| if (labelName.substr(snoozeLength,15) == "/8 - time_hhmm/") { | |
| time = labelName.substr(snoozeLength + 15,timeLength); | |
| if (timeLength == 3) { | |
| time = "0" + time; | |
| } | |
| var isValid = true; | |
| for (var i = 0; i<4; i++) { | |
| if (isNaN(time.substr(i,1))) { | |
| isValid = false; | |
| } | |
| } | |
| if (isValid) { | |
| var hours = parseInt(time.substr(0,2),10); | |
| var minutes = parseInt(time.substr(2,2),10); | |
| if (hours < 0 || hours > 23) { | |
| isValid = false; | |
| } | |
| else if (minutes < 0 || minutes > 59) { | |
| isValid = false; | |
| } | |
| } | |
| if (!isValid) { | |
| time = ""; | |
| } | |
| } | |
| } | |
| return time; | |
| } | |
| function isValidTimeLabel(labelName,snoozeLength) { | |
| var time = getTimeFromLabel(labelName,snoozeLength); | |
| if (time !== "") { | |
| return true; | |
| } | |
| return false; | |
| } | |
| function getDateFromDDMMYYLabel(labelName,snoozeLength) { | |
| var labelLength = labelName.length; | |
| var ddmmyyLength = labelLength - (snoozeLength+17); | |
| var ddmmyy = ""; | |
| if ( labelLength == snoozeLength + 17 + 6) { | |
| if (labelName.substr(snoozeLength,17) == "/9 - date_ddmmyy/") { | |
| ddmmyy = labelName.substr(snoozeLength + 17,6); | |
| var isValid = true; | |
| for (var i = 0; i<6; i++) { | |
| if (isNaN(ddmmyy.substr(i,1))) { | |
| isValid = false; | |
| } | |
| } | |
| if (isValid) { | |
| var dd = parseInt(ddmmyy.substr(0,2),10); | |
| var mm = parseInt(ddmmyy.substr(2,2),10); | |
| var yyyy = 2000 + parseInt(ddmmyy.substr(4,2),10); | |
| isValid = isValidDateValues(dd,mm,yyyy); | |
| } | |
| } | |
| } | |
| if (!isValid) { | |
| ddmmyy = ""; | |
| } | |
| else { | |
| ddmmyy = '20' + ddmmyy.substr(4,2) + "-" + ddmmyy.substr(2,2) + '-' + ddmmyy.substr(0,2); | |
| } | |
| return ddmmyy; | |
| } | |
| function getDateFromMMDDYYLabel(labelName,snoozeLength) { | |
| var labelLength = labelName.length; | |
| var mmddyyLength = labelLength - (snoozeLength+17); | |
| var mmddyy = ""; | |
| if ( labelLength == snoozeLength + 17 + 6) { | |
| if (labelName.substr(snoozeLength,17) == "/9 - date_mmddyy/") { | |
| mmddyy = labelName.substr(snoozeLength + 17,6); | |
| var isValid = true; | |
| for (var i = 0; i<6; i++) { | |
| if (isNaN(mmddyy.substr(i,1))) { | |
| isValid = false; | |
| } | |
| } | |
| if (isValid) { | |
| var dd = parseInt(mmddyy.substr(2,2),10); | |
| var mm = parseInt(mmddyy.substr(0,2),10); | |
| var yyyy = 2000 + parseInt(mmddyy.substr(4,2),10); | |
| isValid = isValidDateValues(dd,mm,yyyy); | |
| } | |
| } | |
| } | |
| if (!isValid) { | |
| mmddyy = ""; | |
| } | |
| else { | |
| mmddyy = '20' + mmddyy.substr(4,2) + "-" + mmddyy.substr(0,2) + '-' + mmddyy.substr(2,2); | |
| } | |
| return mmddyy; | |
| } | |
| function isValidDateValues(dd,mm,yyyy) { | |
| if (mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31 && (yyyy >= 2000 && yyyy <= 9999)) { | |
| if (((mm == 4 || mm == 6 || mm == 9 || mm == 11) && dd <= 30 ) | |
| || (mm == 2 && dd <= 28 || dd <= 29 && isLeapYear(yyyy)) | |
| || (mm != 4 && mm != 6 && mm != 9 && mm != 11 && mm != 2)) { | |
| return true; | |
| } | |
| } | |
| } | |
| function isLeapYear(years) { | |
| if (years % 400 === 0 ) {return true;} | |
| else if (years % 100 === 0 ) {return false;} | |
| else if (years % 4 === 0 ) {return true;} | |
| else {return false;} | |
| } | |
| function isValidDDMMYYLabel(labelName,snoozeLength) { | |
| var ddmmyy = getDateFromDDMMYYLabel(labelName,snoozeLength); | |
| if (ddmmyy !== "") { | |
| return true; | |
| } | |
| return false; | |
| } | |
| function isValidMMDDYYLabel(labelName,snoozeLength) { | |
| var mmddyy = getDateFromMMDDYYLabel(labelName,snoozeLength); | |
| if (mmddyy !== "") { | |
| return true; | |
| } | |
| return false; | |
| } | |
| function getUsersTimeZone() { | |
| return CalendarApp.getTimeZone(); | |
| } | |
| function getDayOfWeek(aDate) { | |
| return Utilities.formatDate(aDate, getUsersTimeZone(), "EEEE"); | |
| } | |
| function getCurrentDay() { | |
| return getDayOfWeek(new Date()); | |
| } | |
| function getCurrentIsoDateAndTime() { | |
| return Utilities.formatDate(new Date(), getUsersTimeZone(), "yyyy-MM-dd-HHmm"); | |
| } | |
| function getCurrentIsoDate() { | |
| return Utilities.formatDate(new Date(), getUsersTimeZone(), "yyyy-MM-dd"); | |
| } | |
| function isDayLabel(labelName) { | |
| if (labelName === SNOOZE_LABEL + "/" + MONDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + TUESDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + WEDNESDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + THURSDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + FRIDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + SATURDAY_LABEL | |
| || labelName === SNOOZE_LABEL + "/" + SUNDAY_LABEL) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| function getUnsnoozeLabel() { | |
| if (unsnoozeLabel === null) { | |
| Logger.log("Load unsnooze label from global"); | |
| unsnoozeLabel = GmailApp.getUserLabelByName(UNSNOOZE_LABEL); | |
| } | |
| if (unsnoozeLabel === null) { | |
| unsnoozeLabel = GmailApp.createLabel(UNSNOOZE_LABEL); | |
| } | |
| else { | |
| Logger.log("unsnooze found"); | |
| } | |
| return unsnoozeLabel; | |
| } | |
| function getSnoozeErrorLabel() { | |
| if (snoozeErrorLabel === null) { | |
| Logger.log("Load snoozeError label from global"); | |
| snoozeErrorLabel = GmailApp.getUserLabelByName(SNOOZE_ERROR_LABEL); | |
| } | |
| if (snoozeErrorLabel === null) { | |
| snoozeErrorLabel = GmailApp.createLabel(SNOOZE_ERROR_LABEL); | |
| } | |
| else { | |
| Logger.log("SnoozeError found"); | |
| } | |
| return snoozeErrorLabel; | |
| } | |
| function initialiseProperty(key,initialValue) { | |
| var value = PropertiesService.getUserProperties().getProperty(key); | |
| if (value === null || value === "") { | |
| PropertiesService.getUserProperties().setProperty(key, initialValue); | |
| } | |
| } | |
| function getCurrentHHMM() { | |
| var now = getCurrentIsoDateAndTime(); | |
| return now.substring(11,15); | |
| } | |
| function isNewDay(today,timeDayStarts) { | |
| var lastDateSaved = PropertiesService.getUserProperties().getProperty(KEY_CURRENT_DAY); | |
| if (lastDateSaved != today && getCurrentHHMM() >= timeDayStarts) { | |
| return true; | |
| } | |
| return false; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment