appscript.dev
Automation Beginner Gmail

Archive newsletters automatically after seven days

Sweep read promotional mail on a daily schedule to keep the inbox clean.

Published Sep 23, 2025

The Northwind inbox fills with newsletters Awadesh reads once and forgets. They are not spam — they are worth a glance — but a week later they are just clutter sitting in the inbox, pushing real work out of view. Archiving them by hand is the kind of chore nobody keeps up.

This script does the sweep on a schedule. Once a day it finds promotional mail that has already been read and is more than seven days old, and archives it. The newsletters stay searchable in All Mail; they just stop crowding the inbox. Anything unread, or newer than a week, is left exactly where it is.

What you’ll need

  • A Gmail account where newsletters land in the Promotions category — the default for most marketing mail.
  • Nothing else to set up. The search itself decides what gets swept, so there is no sheet or label to prepare.

The script

// Gmail search that selects what to sweep: promotional mail in the
// inbox, already read, and older than seven days.
const SWEEP_QUERY = 'in:inbox category:promotions is:read older_than:7d';

/**
 * Finds read promotional mail older than seven days and archives it,
 * clearing newsletters out of the inbox while leaving them searchable.
 */
function archiveOldNewsletters() {
  // 1. Find every thread matching the sweep query.
  const threads = GmailApp.search(SWEEP_QUERY);

  // 2. Nothing matched — stop quietly.
  if (!threads.length) {
    console.log('No newsletters to archive.');
    return;
  }

  // 3. Archive each matching thread out of the inbox.
  threads.forEach((t) => t.moveToArchive());
  console.log(`Archived ${threads.length}`);
}

How it works

  1. archiveOldNewsletters runs the SWEEP_QUERY Gmail search. The query has four parts: in:inbox (still in the inbox), category:promotions (Gmail’s marketing category), is:read (already opened), and older_than:7d (more than a week old).
  2. If nothing matched, it logs that and stops.
  3. Otherwise it calls moveToArchive on each matching thread, which removes it from the inbox but keeps it in All Mail, fully searchable.

Example run

Say the inbox holds these promotional threads when the script runs on 25 May:

NewsletterRead?AgeResult
Design Weeklyread9 daysarchived
Tooling Digestread3 dayskept (too new)
Conference inviteunread12 dayskept (unread)
Studio Newsread8 daysarchived

The log reads Archived 2. The inbox loses the two stale, already-read newsletters; the unread one and the recent one stay put.

Trigger it

Run this on a daily timer so the inbox is swept every morning:

  1. In the Apps Script editor open Triggers and click Add Trigger.
  2. Choose archiveOldNewsletters, set the event source to Time-driven, and pick a Day timer for the 6am to 7am slot.

Once a day is plenty — the seven-day window means there is no rush to catch mail the moment it ages out.

Watch out for

  • It relies on Gmail’s category:promotions being accurate. If a newsletter is misfiled into Primary it is never swept. To be sure, tag newsletters with a Gmail filter and search label:newsletters instead of the category.
  • Only read mail is touched — is:read protects anything you have not opened yet, even if it is months old.
  • moveToArchive only archives; it never deletes. Swept newsletters stay in All Mail and still surface in search.
  • To spare a particular sender, add an exclusion to the query, for example -from:[email protected].
  • GmailApp.search returns at most 500 threads per call. A normal daily sweep is well under that, but a first run on a long-neglected inbox might need to be run a few times to clear the backlog.

Related