Claude Skills Guide

Email snooze functionality has become essential for managing inbox overwhelm. Chrome extensions that implement email snooze scheduling allow users to temporarily remove emails from their inbox and have them reappear at a specified future time. This guide covers the implementation patterns, APIs, and practical considerations for developers building this type of extension.

How Email Snooze Extensions Work

Chrome extensions for email snooze scheduling typically operate by interacting with email provider APIs. The extension intercepts email messages, stores the snooze metadata on a backend or locally, and then uses scheduled triggers to move or relabel those emails back to the inbox at the designated time.

The core architecture involves three main components:

  1. Content Script - Runs in the context of the email provider’s web interface, identifying emails and adding snooze UI elements
  2. Background Service Worker - Handles scheduling logic and API calls
  3. Storage Layer - Maintains snooze state using chrome.storage or a backend database

Manifest V3 Implementation

Modern Chrome extensions must use Manifest V3, which introduces several changes from V2. Here’s a basic manifest structure for an email snooze extension:

{
  "manifest_version": 3,
  "name": "Email Snooze Scheduler",
  "version": "1.0",
  "permissions": [
    "storage",
    "alarms",
    "activeTab",
    "scripting"
  ],
  "host_permissions": [
    "https://mail.google.com/*",
    "https://outlook.office.com/*"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [{
    "matches": [
      "https://mail.google.com/*",
      "https://outlook.office.com/*"
    ],
    "js": ["content.js"]
  }]
}

Core Implementation Patterns

Storing Snooze Data

The chrome.storage API provides persistent storage that works across browser sessions. For email snooze extensions, you’ll need to store the email ID, original label, and scheduled return time.

// content.js - Snooze an email
function snoozeEmail(emailId, snoozeUntil) {
  const snoozeEntry = {
    emailId: emailId,
    originalLabels: ['INBOX'], // Capture current labels
    snoozeUntil: snoozeUntil,
    provider: 'gmail' // or 'outlook', etc.
  };
  
  chrome.storage.local.get(['snoozedEmails'], (result) => {
    const snoozedEmails = result.snoozedEmails || [];
    snoozedEmails.push(snoozeEntry);
    chrome.storage.local.set({ snoozedEmails });
  });
  
  // Notify background script to schedule the alarm
  chrome.runtime.sendMessage({
    action: 'scheduleSnooze',
    emailId: emailId,
    snoozeUntil: snoozeUntil
  });
}

Scheduling with Chrome Alarms

Chrome’s alarms API allows you to schedule future events reliably, even when the extension isn’t actively running:

// background.js
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name.startsWith('snooze-')) {
    const emailId = alarm.name.replace('snooze-', '');
    processSnoozeReturn(emailId);
  }
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'scheduleSnooze') {
    const delay = message.snoozeUntil - Date.now();
    
    if (delay > 0) {
      chrome.alarms.create(`snooze-${message.emailId}`, {
        delayInMinutes: Math.ceil(delay / 60000),
        periodInMinutes: null
      });
    }
  }
});

async function processSnoozeReturn(emailId) {
  // Retrieve stored email metadata
  const result = await chrome.storage.local.get(['snoozedEmails']);
  const snoozedEmails = result.snoozedEmails || [];
  const entry = snoozedEmails.find(e => e.emailId === emailId);
  
  if (entry) {
    // Use provider API to move email back to inbox
    await moveEmailToInbox(entry);
    
    // Clean up storage
    const updated = snoozedEmails.filter(e => e.emailId !== emailId);
    await chrome.storage.local.set({ snoozedEmails: updated });
  }
}

Provider API Integration

Gmail API Integration

For Gmail integration, you’ll need to use the Gmail API to modify email labels:

async function moveEmailToInbox(snoozeEntry) {
  const { accessToken } = await getAccessToken();
  
  // First, remove the snooze label if you added one
  await fetch(
    `https://gmail.googleapis.com/gmail/v1/users/me/messages/${snoozeEntry.emailId}/modify`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        removeLabelIds: ['SNOOZE_LABEL_ID'],
        addLabelIds: ['INBOX']
      })
    }
  );
}

Outlook API Integration

Microsoft Graph API handles Outlook.com and Office 365:

async function moveOutlookEmailToInbox(snoozeEntry) {
  const { accessToken } = await getAccessToken();
  
  // Move message to inbox folder
  await fetch(
    `https://graph.microsoft.com/v1.0/me/messages/${snoozeEntry.emailId}/move`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        destinationId: 'inbox'
      })
    }
  );
}

User Interface Considerations

The snooze UI typically appears as a dropdown or popup when users hover over or select an email. Common preset options include:

Implement custom time selection using a date-time picker:

function showCustomSnoozeDialog() {
  const dialog = document.createElement('div');
  dialog.innerHTML = `
    <div class="snooze-dialog">
      <h3>Schedule Snooze</h3>
      <input type="datetime-local" id="snooze-datetime">
      <button id="confirm-snooze">Snooze</button>
      <button id="cancel-snooze">Cancel</button>
    </div>
  `;
  document.body.appendChild(dialog);
  
  document.getElementById('confirm-snooze').addEventListener('click', () => {
    const datetime = document.getElementById('snooze-datetime').value;
    const snoozeUntil = new Date(datetime).getTime();
    snoozeEmail(currentEmailId, snoozeUntil);
    dialog.remove();
  });
}

Security and Privacy

Email snooze extensions handle sensitive data, so implement these security practices:

  1. Minimal Permissions - Request only the scopes needed for email access
  2. Secure Token Storage - Use chrome.storage.session for access tokens when possible
  3. Content Security Policy - Restrict script sources in your manifest
  4. OAuth 2.0 Flow - Never store user passwords directly
{
  "oauth2": {
    "client_id": "YOUR_CLIENT_ID",
    "scopes": [
      "https://www.googleapis.com/auth/gmail.modify",
      "https://www.googleapis.com/auth/gmail.readonly"
    ]
  }
}

Building a Custom Solution

For developers building their own snooze functionality, start with the fundamental patterns shown here and expand based on your specific requirements. Consider supporting multiple email providers, implementing snooze categories (work, personal, follow-up), and adding notification reminders before emails reappear.

The key is maintaining reliable scheduling even when the browser is closed, which requires combining chrome.alarms with a lightweight backend or leveraging the browser’s built-in scheduling capabilities effectively.

Built by theluckystrike — More at zovo.one