Add Gmail label cleanup script for inbox-zero migration
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* Gmail Label Cleanup Script
|
||||
* Run from https://script.google.com
|
||||
*
|
||||
* What this does:
|
||||
* 1. Merges old labels into inbox-zero categories (relabels all threads)
|
||||
* 2. Archives + relabels cvlp threads to Newsletter
|
||||
* 3. Merges purchases into Receipt, deletes purchases
|
||||
* 4. Moves donations top-level, selling under business
|
||||
* 5. Deletes contract label (threads stay under business)
|
||||
* 6. Deletes empty/unused labels
|
||||
*
|
||||
* Safe to run multiple times - skips labels that don't exist.
|
||||
*/
|
||||
|
||||
// ─── STEP 1: Merge old labels into inbox-zero categories ─────────────────────
|
||||
|
||||
function mergeLabels() {
|
||||
var merges = [
|
||||
{ from: 'promo', to: 'Marketing' },
|
||||
{ from: 'mailing list', to: 'Newsletter' },
|
||||
{ from: 'twitter', to: 'Notification' },
|
||||
{ from: 'facebook', to: 'Notification' },
|
||||
{ from: 'tech', to: 'Newsletter' },
|
||||
{ from: 'To Reply', to: 'Awaiting Reply' },
|
||||
];
|
||||
|
||||
merges.forEach(function(m) {
|
||||
var fromLabel = GmailApp.getUserLabelByName(m.from);
|
||||
if (!fromLabel) {
|
||||
Logger.log('Skipping (not found): ' + m.from);
|
||||
return;
|
||||
}
|
||||
|
||||
var toLabel = GmailApp.getUserLabelByName(m.to);
|
||||
if (!toLabel) {
|
||||
Logger.log('Creating label: ' + m.to);
|
||||
toLabel = GmailApp.createLabel(m.to);
|
||||
}
|
||||
|
||||
Logger.log('Merging ' + m.from + ' -> ' + m.to);
|
||||
var threads = fromLabel.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.addLabelToThreads(threads, toLabel);
|
||||
GmailApp.removeLabelFromThreads(threads, fromLabel);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = fromLabel.getThreads(0, 500);
|
||||
}
|
||||
Logger.log('Moved ' + total + ' threads: ' + m.from + ' -> ' + m.to);
|
||||
fromLabel.deleteLabel();
|
||||
Logger.log('Deleted label: ' + m.from);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── STEP 2: cvlp → Newsletter + archive ─────────────────────────────────────
|
||||
|
||||
function archiveCvlp() {
|
||||
var cvlpLabel = GmailApp.getUserLabelByName('cvlp');
|
||||
if (!cvlpLabel) {
|
||||
Logger.log('cvlp label not found, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
var newsletterLabel = GmailApp.getUserLabelByName('Newsletter');
|
||||
if (!newsletterLabel) {
|
||||
newsletterLabel = GmailApp.createLabel('Newsletter');
|
||||
}
|
||||
|
||||
Logger.log('Processing cvlp: relabeling to Newsletter and archiving...');
|
||||
var threads = cvlpLabel.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.addLabelToThreads(threads, newsletterLabel);
|
||||
GmailApp.removeLabelFromThreads(threads, cvlpLabel);
|
||||
GmailApp.moveThreadsToArchive(threads);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = cvlpLabel.getThreads(0, 500);
|
||||
}
|
||||
Logger.log('Archived ' + total + ' cvlp threads');
|
||||
cvlpLabel.deleteLabel();
|
||||
Logger.log('Deleted label: cvlp');
|
||||
}
|
||||
|
||||
// ─── STEP 3: Merge purchases into Receipt ────────────────────────────────────
|
||||
|
||||
function mergePurchasesIntoReceipt() {
|
||||
var purchasesLabel = GmailApp.getUserLabelByName('purchases');
|
||||
if (!purchasesLabel) {
|
||||
Logger.log('purchases label not found, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
var receiptLabel = GmailApp.getUserLabelByName('Receipt');
|
||||
if (!receiptLabel) {
|
||||
receiptLabel = GmailApp.createLabel('Receipt');
|
||||
}
|
||||
|
||||
Logger.log('Merging purchases -> Receipt...');
|
||||
var threads = purchasesLabel.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.addLabelToThreads(threads, receiptLabel);
|
||||
GmailApp.removeLabelFromThreads(threads, purchasesLabel);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = purchasesLabel.getThreads(0, 500);
|
||||
}
|
||||
Logger.log('Moved ' + total + ' threads: purchases -> Receipt');
|
||||
purchasesLabel.deleteLabel();
|
||||
Logger.log('Deleted label: purchases');
|
||||
}
|
||||
|
||||
// ─── STEP 4: Restructure business nested labels ───────────────────────────────
|
||||
|
||||
function restructureBusinessLabels() {
|
||||
// Move donations top-level: rename business/donations -> donations
|
||||
var bizDonations = GmailApp.getUserLabelByName('business/donations');
|
||||
if (bizDonations) {
|
||||
var donationsLabel = GmailApp.getUserLabelByName('donations');
|
||||
if (!donationsLabel) {
|
||||
donationsLabel = GmailApp.createLabel('donations');
|
||||
}
|
||||
Logger.log('Moving business/donations -> donations (top-level)');
|
||||
var threads = bizDonations.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.addLabelToThreads(threads, donationsLabel);
|
||||
GmailApp.removeLabelFromThreads(threads, bizDonations);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = bizDonations.getThreads(0, 500);
|
||||
}
|
||||
Logger.log('Moved ' + total + ' threads to top-level donations');
|
||||
bizDonations.deleteLabel();
|
||||
} else {
|
||||
// Try top-level donations label
|
||||
Logger.log('business/donations not found - checking for top-level donations label');
|
||||
}
|
||||
|
||||
// Move selling under business: rename selling -> business/selling
|
||||
var sellingLabel = GmailApp.getUserLabelByName('selling');
|
||||
if (sellingLabel) {
|
||||
var bizSelling = GmailApp.getUserLabelByName('business/selling');
|
||||
if (!bizSelling) {
|
||||
bizSelling = GmailApp.createLabel('business/selling');
|
||||
}
|
||||
Logger.log('Moving selling -> business/selling');
|
||||
var threads = sellingLabel.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.addLabelToThreads(threads, bizSelling);
|
||||
GmailApp.removeLabelFromThreads(threads, sellingLabel);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = sellingLabel.getThreads(0, 500);
|
||||
}
|
||||
Logger.log('Moved ' + total + ' threads to business/selling');
|
||||
sellingLabel.deleteLabel();
|
||||
}
|
||||
|
||||
// Delete contract label (threads already have business label, just remove contract)
|
||||
var contractLabel = GmailApp.getUserLabelByName('business/contract');
|
||||
if (!contractLabel) {
|
||||
contractLabel = GmailApp.getUserLabelByName('contract');
|
||||
}
|
||||
if (contractLabel) {
|
||||
Logger.log('Removing contract label from all threads...');
|
||||
var threads = contractLabel.getThreads(0, 500);
|
||||
var total = 0;
|
||||
while (threads.length > 0) {
|
||||
GmailApp.removeLabelFromThreads(threads, contractLabel);
|
||||
total += threads.length;
|
||||
Utilities.sleep(1000);
|
||||
threads = contractLabel.getThreads(0, 500);
|
||||
}
|
||||
contractLabel.deleteLabel();
|
||||
Logger.log('Deleted contract label (' + total + ' threads unaffected)');
|
||||
}
|
||||
}
|
||||
|
||||
// ─── STEP 5: Delete unused labels ────────────────────────────────────────────
|
||||
|
||||
function deleteUnusedLabels() {
|
||||
var toDelete = [
|
||||
'Notes',
|
||||
'[Mailbox]',
|
||||
'Later',
|
||||
'To Buy',
|
||||
'To Read',
|
||||
'To Watch',
|
||||
'Cold Email',
|
||||
'Oak Ridge Moms',
|
||||
'music',
|
||||
];
|
||||
|
||||
toDelete.forEach(function(name) {
|
||||
var label = GmailApp.getUserLabelByName(name);
|
||||
if (!label) {
|
||||
Logger.log('Not found (already gone?): ' + name);
|
||||
return;
|
||||
}
|
||||
var count = label.getThreads(0, 1).length;
|
||||
if (count > 0) {
|
||||
Logger.log('WARNING: ' + name + ' still has threads - removing label from them first');
|
||||
var threads = label.getThreads(0, 500);
|
||||
while (threads.length > 0) {
|
||||
GmailApp.removeLabelFromThreads(threads, label);
|
||||
Utilities.sleep(500);
|
||||
threads = label.getThreads(0, 500);
|
||||
}
|
||||
}
|
||||
label.deleteLabel();
|
||||
Logger.log('Deleted: ' + name);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── RUN ALL ──────────────────────────────────────────────────────────────────
|
||||
|
||||
function runAll() {
|
||||
Logger.log('=== Starting Gmail label cleanup ===');
|
||||
Logger.log('--- Step 1: Merging labels ---');
|
||||
mergeLabels();
|
||||
Logger.log('--- Step 2: Archiving cvlp ---');
|
||||
archiveCvlp();
|
||||
Logger.log('--- Step 3: Merging purchases into Receipt ---');
|
||||
mergePurchasesIntoReceipt();
|
||||
Logger.log('--- Step 4: Restructuring business labels ---');
|
||||
restructureBusinessLabels();
|
||||
Logger.log('--- Step 5: Deleting unused labels ---');
|
||||
deleteUnusedLabels();
|
||||
Logger.log('=== Done! ===');
|
||||
}
|
||||
Reference in New Issue
Block a user