Skip to main content
Glama
organize-everything.jsโ€ข13.9 kB
#!/usr/bin/env node import { FastMailClient } from '../src/fastmail-client.js'; import dotenv from 'dotenv'; dotenv.config({ path: '../.env' }); async function organizeEverything() { console.log('๐Ÿ”ฅ ORGANIZING ALL 8,000+ EMAILS - 100% COMPLETION\n'); const client = new FastMailClient( process.env.FASTMAIL_API_TOKEN, 'clark@clarkeverson.com', 'clark@clarkeverson.com', 'clarkeverson.com', 'https://api.fastmail.com/jmap/session' ); try { await client.authenticate(); const mailboxes = await client.getMailboxes(); // Get target hierarchical folders const infoParent = mailboxes.find(mb => mb.name === 'Information'); const financialParent = mailboxes.find(mb => mb.name === 'Financial'); const commerceParent = mailboxes.find(mb => mb.name === 'Commerce'); const professionalParent = mailboxes.find(mb => mb.name === 'Professional'); const personalParent = mailboxes.find(mb => mb.name === 'Personal'); const targets = { 'Information/Newsletters': mailboxes.find(mb => mb.parentId === infoParent?.id && mb.name === 'Newsletters'), 'Information/News': mailboxes.find(mb => mb.parentId === infoParent?.id && mb.name === 'News'), 'Financial/Receipts': mailboxes.find(mb => mb.parentId === financialParent?.id && mb.name === 'Receipts'), 'Financial/Banking': mailboxes.find(mb => mb.parentId === financialParent?.id && mb.name === 'Banking'), 'Financial/Bills': mailboxes.find(mb => mb.parentId === financialParent?.id && mb.name === 'Bills'), 'Commerce/Orders': mailboxes.find(mb => mb.parentId === commerceParent?.id && mb.name === 'Orders'), 'Commerce/Subscriptions': mailboxes.find(mb => mb.parentId === commerceParent?.id && mb.name === 'Subscriptions'), 'Professional/GitHub': mailboxes.find(mb => mb.parentId === professionalParent?.id && mb.name === 'GitHub'), 'Professional/Security': mailboxes.find(mb => mb.parentId === professionalParent?.id && mb.name === 'Security'), 'Personal/Health': mailboxes.find(mb => mb.parentId === personalParent?.id && mb.name === 'Health'), 'Personal/Travel': mailboxes.find(mb => mb.parentId === personalParent?.id && mb.name === 'Travel') }; console.log('๐ŸŽฏ TARGET FOLDERS:'); Object.entries(targets).forEach(([name, mb]) => { console.log(`${mb ? 'โœ…' : 'โŒ'} ${name}`); }); // Find ALL folders with emails that need organizing const systemFolders = ['Inbox', 'Sent', 'Drafts', 'Trash', 'Spam']; const hierarchicalFolders = ['Information', 'Financial', 'Commerce', 'Professional', 'Personal']; const skipFolders = [...systemFolders, ...hierarchicalFolders, 'Archive']; const foldersToOrganize = mailboxes.filter(mb => !skipFolders.includes(mb.name) && mb.totalEmails > 0 && !mb.parentId // Only root level folders ); console.log('\n๐Ÿ“‚ FOLDERS WITH EMAILS TO ORGANIZE:'); console.log('='.repeat(60)); let totalEmailsToOrganize = 0; foldersToOrganize.forEach(folder => { console.log(`๐Ÿ“‚ ${folder.name}: ${folder.totalEmails} emails`); totalEmailsToOrganize += folder.totalEmails; }); console.log(`\n๐Ÿ“Š TOTAL EMAILS TO ORGANIZE: ${totalEmailsToOrganize}`); // Also check Archive folder - it has 5,412 emails that could be organized const archiveFolder = mailboxes.find(mb => mb.name === 'Archive'); if (archiveFolder && archiveFolder.totalEmails > 0) { console.log(`\n๐Ÿ“ Archive folder has ${archiveFolder.totalEmails} emails`); console.log('These could also be organized into hierarchical structure'); foldersToOrganize.push(archiveFolder); totalEmailsToOrganize += archiveFolder.totalEmails; } console.log(`\n๐Ÿ”ฅ ORGANIZING ${totalEmailsToOrganize} EMAILS FROM ALL FOLDERS:`); console.log('='.repeat(80)); let totalProcessed = 0; // Process each folder for (const folder of foldersToOrganize) { console.log(`\n๐Ÿ“‚ PROCESSING: ${folder.name} (${folder.totalEmails} emails)`); console.log('-'.repeat(50)); try { let position = 0; let folderProcessed = 0; while (position < folder.totalEmails) { const emailResult = await client.getEmails(folder.id, 50, position); if (!emailResult?.emails?.length) break; console.log(` ๐Ÿ“ง Batch: emails ${position + 1}-${position + emailResult.emails.length}`); for (const email of emailResult.emails) { try { const sender = email.from?.[0]?.email?.toLowerCase() || ''; const subject = email.subject?.toLowerCase() || ''; const senderDomain = sender.split('@')[1]?.toLowerCase() || ''; let targetPath = null; // FINANCIAL CATEGORIZATION if ( // Banking sender.includes('bank') || sender.includes('chase') || sender.includes('fidelity') || sender.includes('schwab') || sender.includes('credit') || sender.includes('financial') || senderDomain.includes('bank') || senderDomain.includes('schwab') || subject.includes('statement') || subject.includes('balance') || subject.includes('account') ) { targetPath = 'Financial/Banking'; } // Receipts/Payments else if ( sender.includes('paypal') || sender.includes('stripe') || sender.includes('payment') || sender.includes('billing') || sender.includes('invoice') || subject.includes('receipt') || subject.includes('payment') || subject.includes('invoice') || subject.includes('transaction') || subject.includes('order') && subject.includes('total') ) { targetPath = 'Financial/Receipts'; } // Bills else if ( subject.includes('bill') || subject.includes('due') || subject.includes('overdue') || sender.includes('utility') || sender.includes('electric') || sender.includes('gas') ) { targetPath = 'Financial/Bills'; } // COMMERCE CATEGORIZATION else if ( // Orders/Shopping sender.includes('amazon') || sender.includes('etsy') || sender.includes('shop') || sender.includes('store') || sender.includes('retail') || sender.includes('order') || senderDomain.includes('amazon') || senderDomain.includes('etsy') || subject.includes('order') || subject.includes('shipped') || subject.includes('delivered') || subject.includes('tracking') || subject.includes('shipment') ) { targetPath = 'Commerce/Orders'; } // Subscriptions else if ( sender.includes('subscription') || sender.includes('membership') || subject.includes('subscription') || subject.includes('membership') || subject.includes('renewal') || subject.includes('expire') ) { targetPath = 'Commerce/Subscriptions'; } // PROFESSIONAL CATEGORIZATION else if ( // GitHub/Development sender.includes('github') || sender.includes('gitlab') || sender.includes('git') || sender.includes('developer') || sender.includes('code') || senderDomain.includes('github') || subject.includes('github') || subject.includes('git') || subject.includes('code') || subject.includes('build') || subject.includes('deploy') || subject.includes('commit') ) { targetPath = 'Professional/GitHub'; } // Security else if ( subject.includes('security') || subject.includes('login') || subject.includes('password') || subject.includes('authentication') || subject.includes('verify') || subject.includes('2fa') || sender.includes('security') || sender.includes('auth') ) { targetPath = 'Professional/Security'; } // PERSONAL CATEGORIZATION else if ( // Health sender.includes('health') || sender.includes('medical') || sender.includes('doctor') || sender.includes('hospital') || sender.includes('clinic') || sender.includes('pharmacy') || senderDomain.includes('health') || senderDomain.includes('medical') || subject.includes('health') || subject.includes('medical') || subject.includes('doctor') || subject.includes('appointment') || subject.includes('prescription') ) { targetPath = 'Personal/Health'; } // Travel else if ( sender.includes('travel') || sender.includes('flight') || sender.includes('hotel') || sender.includes('airline') || sender.includes('booking') || sender.includes('airbnb') || senderDomain.includes('travel') || senderDomain.includes('airline') || subject.includes('flight') || subject.includes('hotel') || subject.includes('travel') || subject.includes('booking') || subject.includes('reservation') ) { targetPath = 'Personal/Travel'; } // INFORMATION CATEGORIZATION else if ( // News sender.includes('news') || sender.includes('wsj') || sender.includes('nytimes') || sender.includes('cnn') || sender.includes('bbc') || sender.includes('reuters') || senderDomain.includes('news') || senderDomain.includes('wsj') || subject.includes('breaking') || subject.includes('headlines') || subject.includes('news') ) { targetPath = 'Information/News'; } // Newsletters (everything else automated) else if ( sender.includes('noreply') || sender.includes('no-reply') || sender.includes('newsletter') || sender.includes('notification') || sender.includes('update') || sender.includes('digest') || sender.includes('marketing') || sender.includes('promo') || subject.includes('newsletter') || subject.includes('update') || subject.includes('digest') || subject.includes('unsubscribe') || subject.includes('marketing') ) { targetPath = 'Information/Newsletters'; } // DEFAULT - categorize by domain patterns else if (senderDomain) { if (senderDomain.includes('bank') || senderDomain.includes('financial')) { targetPath = 'Financial/Banking'; } else if (senderDomain.includes('shop') || senderDomain.includes('store')) { targetPath = 'Commerce/Orders'; } else if (senderDomain.includes('health') || senderDomain.includes('medical')) { targetPath = 'Personal/Health'; } else { targetPath = 'Information/Newsletters'; // Default for everything else } } else { targetPath = 'Information/Newsletters'; // Fallback } // Move email to target folder if (targetPath && targets[targetPath]) { await client.moveEmailsToMailbox([email.id], targets[targetPath].id); folderProcessed++; totalProcessed++; if (folderProcessed % 10 === 0) { console.log(` โœ… ${folderProcessed} emails moved to various categories`); } } } catch (error) { console.log(` โŒ Error processing email: ${error.message}`); } } position += emailResult.emails.length; // Progress update console.log(` ๐Ÿ“Š Processed ${Math.min(position, folder.totalEmails)}/${folder.totalEmails} from ${folder.name}`); // Small delay to prevent overwhelming the API await new Promise(resolve => setTimeout(resolve, 1000)); // Break if we've processed enough for this session if (totalProcessed >= 1000) { console.log(`\nโธ๏ธ Pausing at ${totalProcessed} emails processed - continuing in next batch`); break; } } console.log(`โœ… Completed ${folder.name}: ${folderProcessed} emails organized`); if (totalProcessed >= 1000) break; // Stop processing more folders for this session } catch (error) { console.log(`โŒ Error processing folder ${folder.name}: ${error.message}`); } } console.log('\n๐ŸŽ‰ EMAIL ORGANIZATION SESSION COMPLETE!'); console.log('='.repeat(60)); console.log(`๐Ÿ“ง Emails organized this session: ${totalProcessed}`); console.log(`๐Ÿ“Š Progress: Moving toward 100% organization`); if (totalProcessed >= 1000) { console.log('\n๐Ÿ”„ CONTINUE PROCESSING:'); console.log('Run this script again to continue organizing remaining emails'); } else { console.log('\nโœ… ALL EMAILS HAVE BEEN ORGANIZED!'); } } catch (error) { console.log('โŒ Error:', error.message); } } organizeEverything().catch(console.error);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gr3enarr0w/fastmail-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server