Files
docker-infrastructure/inbox-zero/gmail-filter-cleanup.gs
T

262 lines
8.1 KiB
JavaScript

/**
* Gmail Filter Cleanup Script
* Run from https://script.google.com
*
* SETUP REQUIRED:
* Before running, enable the Gmail Advanced Service:
* 1. Click "+" next to "Services" in the left sidebar
* 2. Find "Gmail API" and add it
*
* Run dryRun() first to see what will be deleted.
* Run deleteFilters() to actually delete them.
*/
// Patterns to match against filter "from" criteria.
// Any filter whose "from" contains one of these strings will be deleted.
var DELETE_FROM_PATTERNS = [
// Dead services
'mozy.com',
'ingdirect.com',
'stumbleupon.com',
'plaxo.com',
'jott.com',
'svpply.com',
'alice@email.aliceupdates.com',
'telltalegames.com',
'gymboree.com',
'landofnod.com',
'evganews@evga.com',
'thinkgeek.com',
'recyclebank.com',
'sharebuilder.com',
'zulily.com',
// Political / campaign (no longer relevant)
'barackobama.com',
'berniesanders.com',
'democrats.org',
'rockthevote.com',
'rockthevote',
// No longer relevant (uncertain ones user confirmed)
'vacationsurvey@vargaresearch.com',
'5h4rpd0g@gmail.com',
'mdegan@jacsmechanical.com',
'ispcm-conf.org',
'tntechnology.org',
'Jason Mechler',
// Duplicates / inbox-zero handles these via AI
'nytimes@email.newyorktimes.com',
'nytimes@e.newyorktimesinfo.com',
'redcross-email@usa.redcross.org',
'redcross-email@redcross.org',
'redcross@theamericanredcross.org',
'xfinity@info.xfinity.com',
'xfinity@emails.xfinity.com',
'kirkusreviews.com',
'smarttoys@aol.com',
'spotify@email.news.spotifymail.com',
'no-reply@news.spotifymail.com',
'newsletters@audible.com',
'fightingback@messages.cancer.org',
'@messages.cancer.org',
// Newsletter/marketing — inbox-zero AI handles these
'eff.org',
'rccetimes.com',
'group-digests@linkedin.com',
'info.knologyupclose.com',
'newsletter@theorangepeel.net',
'microsoft@e-mail.microsoft.com',
'newsletters-no-reply@myfonts.com',
'act@credoaction.com',
'yourpowertip@powershell.com',
'email@email.microsoftemail.com',
'ramit@iwillteachyoutoberich.com',
'mkt@manning.com',
'deals@livingsocial.com',
'idera.com',
'newsletter@kirkusreviews.com',
'email@earthfare-email.com',
'gameinfo@email2.telltalegames.com',
'no-reply@mail.goodreads.com',
'angieslist@members.angieslist.com',
'reply@e.taxact.com',
'josabank@shop.josbank.com',
'frenchpaperco@gmail.com',
'csaimages@frenchpaper.com',
'mailman@xoxide.com',
'info@petsafe.net',
'flor@news.flor.com',
'info@launchtn.org',
'alumni@tntech.edu',
'info@rockthevote.com',
'payscalemonitor@mail.payscale.com',
'statefarm@e.statefarm.com',
'mailer@svpply.com',
'noreply@dontcrack.com',
'info@paperandpolkadots.com',
'dennis@adirondackguitar.com',
'Yamaha_Corporation_of_America@mail.vresp.com',
'carters.email@e.carters.com',
'FTD@email.ftd.com',
'info@email.glassdoor.com',
'reply@glassdoor.com',
'customerservice@1800petmeds.com',
'news@crownclub.regmovies.com',
'autonationspecials@autonation.chtah.com',
'EddieBauerEmail@em.eddiebauer.com',
'email@style.ballarddesigns.com',
'barnesandnoble@m.bn.com',
'sales@xoxide.com',
'tripadvisor.com',
'noreply@youtube.com',
'donotreply@proguitarshop.com',
'info@knoxvilleacademyofmusic.com',
'artistupdates@reverbnation.com',
'promotion@mwave.com',
'deansbeans.com',
'express@e.express.com',
'alice@email.aliceupdates.com',
'ispcm-conf.org',
'no_reply@jetbrains.com',
'noreply@roddenberry.com',
'yourhondadealer@ahmdcms.com',
'mdegan@jacsmechanical.com',
];
// Subject patterns — delete filters matching these subjects
// (only when combined with a dead/irrelevant from, handled separately below)
// For now these are standalone subject-only filters to delete
var DELETE_SUBJECT_PATTERNS = [
'Abandonia Newsletter',
];
// List patterns (mailing list ID in filter query)
var DELETE_LIST_PATTERNS = [
'oakridgemoms.googlegroups.com',
'14-days.googlegroups.com',
'120331169_84238_19051',
'andrewbird.fanbridge.com',
];
// Specific from+subject combos — delete if BOTH match
var DELETE_FROM_SUBJECT_PAIRS = [
{ from: 'linkedin.com', subject: 'endorsed' },
{ from: 'updates@linkedin.com', subject: null }, // skip inbox only, no label
{ from: 'connections@linkedin.com', subject: null }, // linkedin connection spam
{ from: 'noreply@plaxo.com', subject: 'birthday' },
{ from: 'confirm+ye22mger@facebookmail.com', subject: null }, // old specific fb filter
];
// ─────────────────────────────────────────────────────────────────────────────
function getFiltersToDelete_() {
var response = Gmail.Users.Settings.Filters.list('me');
var filters = response.filter || [];
var toDelete = [];
filters.forEach(function(f) {
var from = (f.criteria && f.criteria.from) ? f.criteria.from.toLowerCase() : '';
var subject = (f.criteria && f.criteria.subject) ? f.criteria.subject.toLowerCase() : '';
var query = (f.criteria && f.criteria.query) ? f.criteria.query.toLowerCase() : '';
var shouldDelete = false;
var reason = '';
// Check from patterns
DELETE_FROM_PATTERNS.forEach(function(p) {
if (from.indexOf(p.toLowerCase()) !== -1) {
shouldDelete = true;
reason = 'from matches: ' + p;
}
});
// Check subject patterns
if (!shouldDelete) {
DELETE_SUBJECT_PATTERNS.forEach(function(p) {
if (subject.indexOf(p.toLowerCase()) !== -1) {
shouldDelete = true;
reason = 'subject matches: ' + p;
}
});
}
// Check list patterns in query
if (!shouldDelete) {
DELETE_LIST_PATTERNS.forEach(function(p) {
if (query.indexOf(p.toLowerCase()) !== -1) {
shouldDelete = true;
reason = 'list matches: ' + p;
}
});
}
// Check from+subject pairs
if (!shouldDelete) {
DELETE_FROM_SUBJECT_PAIRS.forEach(function(pair) {
var fromMatch = pair.from ? from.indexOf(pair.from.toLowerCase()) !== -1 : true;
var subjectMatch = pair.subject ? subject.indexOf(pair.subject.toLowerCase()) !== -1 : true;
if (fromMatch && subjectMatch && (pair.from || pair.subject)) {
shouldDelete = true;
reason = 'pair match: from=' + pair.from + ' subject=' + pair.subject;
}
});
}
if (shouldDelete) {
toDelete.push({ id: f.id, criteria: f.criteria, action: f.action, reason: reason });
}
});
return { all: filters, toDelete: toDelete };
}
function dryRun() {
Logger.log('=== DRY RUN — no filters will be deleted ===');
var result = getFiltersToDelete_();
Logger.log('Total filters: ' + result.all.length);
Logger.log('Filters that WOULD be deleted: ' + result.toDelete.length);
Logger.log('');
result.toDelete.forEach(function(f) {
Logger.log('DELETE [' + f.id + ']');
Logger.log(' From: ' + (f.criteria.from || ''));
Logger.log(' Subject: ' + (f.criteria.subject || ''));
Logger.log(' Query: ' + (f.criteria.query || ''));
Logger.log(' Reason: ' + f.reason);
Logger.log('');
});
Logger.log('=== Filters that will be KEPT ===');
var kept = result.all.filter(function(f) {
return !result.toDelete.some(function(d) { return d.id === f.id; });
});
kept.forEach(function(f) {
Logger.log('KEEP [' + f.id + '] from=' + (f.criteria.from || '') +
' subject=' + (f.criteria.subject || '') +
' query=' + (f.criteria.query || ''));
});
}
function deleteFilters() {
Logger.log('=== Deleting filters ===');
var result = getFiltersToDelete_();
Logger.log('Deleting ' + result.toDelete.length + ' of ' + result.all.length + ' filters...');
var deleted = 0;
result.toDelete.forEach(function(f) {
try {
Gmail.Users.Settings.Filters.remove('me', f.id);
Logger.log('Deleted [' + f.id + '] from=' + (f.criteria.from || '') + ' (' + f.reason + ')');
deleted++;
Utilities.sleep(200);
} catch(e) {
Logger.log('ERROR deleting [' + f.id + ']: ' + e.message);
}
});
Logger.log('Done. Deleted ' + deleted + ' filters.');
Logger.log('Remaining: ' + (result.all.length - deleted) + ' filters.');
}