code icon Code

Mark Gmail Messages Read

Mark multiple Gmail messages as read by removing the UNREAD label

Source Code

import fs from 'fs';

const [messageIdsArg = '', outputPath = 'session/gmail-mark-results.json'] = process.argv.slice(2);

const messageIds = messageIdsArg
  .split(',')
  .map(id => id.trim())
  .filter(Boolean);

if (messageIds.length === 0) {
  console.error('No message IDs provided');
  console.log(JSON.stringify({ success: false, error: 'no_message_ids' }));
  process.exit(1);
}

console.log(`Marking ${messageIds.length} message(s) as read...`);

/**
 * Mark messages as read using Gmail batch modify API
 * Marks as read by removing UNREAD label
 */
async function markMessagesRead(ids) {
  const BATCH_SIZE = 50; // Gmail batch limit
  const results = { marked: [], failed: [] };

  for (let i = 0; i < ids.length; i += BATCH_SIZE) {
    const batch = ids.slice(i, i + BATCH_SIZE);

    const res = await fetch(
      'https://gmail.googleapis.com/gmail/v1/users/me/messages/batchModify',
      {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer PLACEHOLDER_TOKEN',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          ids: batch,
          removeLabelIds: ['UNREAD'],
        }),
      }
    );

    if (res.ok) {
      results.marked.push(...batch);
      console.log(`  Marked ${results.marked.length}/${ids.length} as read...`);
    } else {
      const errorText = await res.text();
      console.error(`Batch failed: ${res.status} - ${errorText}`);
      results.failed.push(...batch);
    }
  }

  return results;
}

try {
  const results = await markMessagesRead(messageIds);

  // Write results
  const dir = outputPath.split('/').slice(0, -1).join('/');
  if (dir) fs.mkdirSync(dir, { recursive: true });

  const output = {
    success: results.failed.length === 0,
    markedAt: new Date().toISOString(),
    markedCount: results.marked.length,
    failedCount: results.failed.length,
    marked: results.marked,
    failed: results.failed,
  };

  fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));

  console.log(`\nāœ“ Marked ${results.marked.length} message(s) as read`);
  if (results.failed.length > 0) {
    console.log(`āœ— Failed to mark ${results.failed.length} message(s)`);
  }

  console.log(JSON.stringify(output));
} catch (error) {
  console.error('Mark as read failed:', error.message);
  throw error;
}