- Last verified: February 23, 2026
- Goal: Automatically move notification emails older than 7 days to Trash in Gmail.
Gmail filters can label/organize incoming messages, but they do not provide a native “delete after N days” retention rule. The reliable pattern is:
- Use a Gmail filter to apply a dedicated label (example:
github-ci) - Run a daily Google Apps Script that searches
older_than:7dand trashes matching threads
- Gmail Filter: identifies noisy notifications
- Label:
github-ci(or any label you choose) - Apps Script: runs daily, searches old labeled threads, moves them to Trash
- Trigger: time-driven, once per day
- Open Gmail:
https://mail.google.com - Left sidebar -> More -> Create new label
- Name it
github-ci(or e.g.noisy-notifications)
Important: a new label starts empty until emails are assigned to it.
- In Gmail search bar, click the filter/options icon
- Build criteria (example for GitHub CI):
- From:
notifications@github.com - Subject:
workflow OR failed OR succeeded OR run - Optional: add repo keyword in “Has the words”, e.g.
"owner/repo"
- From:
- Click Create filter
- Check Apply the label
- Select/create label
github-ci - (Optional but recommended for initial backfill) check Also apply filter to matching conversations
- Click Create filter
If you don’t check “Also apply filter to matching conversations”, the label will be applied only to new incoming matching emails.
- Open:
https://script.google.com - Click New project
- Replace default code with the script below
- Save project (example:
gmail-notification-cleanup)
function deleteOldLabeledNotifications() {
// Label assigned by your Gmail filter (change if needed)
const LABEL = "github-ci";
// Keep emails newer than this many days
const DAYS = 7;
// Number of threads fetched per search loop
const SEARCH_BATCH = 500;
// Gmail API limit: max 100 threads per moveThreadsToTrash call
const MOVE_BATCH = 100;
// Gmail search query:
// - only threads with the chosen label
// - older than N days
// - not already in Trash
const query = `label:${LABEL} older_than:${DAYS}d -in:trash`;
// Keep processing until no matching threads remain
while (true) {
// Fetch a batch of matching threads
const threads = GmailApp.search(query, 0, SEARCH_BATCH);
// Stop when there is nothing left to process
if (!threads.length) break;
// Move threads to Trash in chunks of 100 to respect Gmail limit
for (let i = 0; i < threads.length; i += MOVE_BATCH) {
const chunk = threads.slice(i, i + MOVE_BATCH);
GmailApp.moveThreadsToTrash(chunk);
}
}
}- In Apps Script, select function deleteOldLabeledNotifications
- Click Run
- Complete Google authorization prompts
- Verify in Gmail:
- old matching labeled threads moved to Trash
- recent threads remain untouched
Temporarily set:
- const DAYS = 14;
Validate behavior, then switch back to 7.
- In Apps Script, open Triggers (clock icon)
- Click Add Trigger
- Configure:
- Function: deleteOldLabeledNotifications
- Event source: Time-driven
- Type: Day timer
- Frequency: Every day
- Save
- Create another label (examples: build-bots, social-digests, billing-alerts)
- Create Gmail filter(s) that apply that label
- Either:
- duplicate script function per label, or
- make LABEL configurable and run multiple triggers/functions
- Expected if filter was just created and no new matching email arrived
- Or filter criteria are too strict
- Or you didn’t enable “Also apply filter to matching conversations”
- Tighten filter using:
- exact sender
- exact subject keywords
- repo/project keyword
- You must batch trash operations in chunks of 100 (already handled in script above)
- Re-run function manually
- Re-grant permissions
- Ensure Gmail and Apps Script are opened under the same account/mailbox
- Script moves emails to Trash, not immediate permanent delete
- Gmail generally auto-deletes Trash after ~30 days
- If desired, keep a larger retention (e.g. 14 or 30 days) for less aggressive cleanup
- Gmail search operators (older_than, label, etc.): https://support.google.com/mail/answer/7190?hl=en
- Gmail filters: https://support.google.com/mail/answer/6579?hl=en
- Apps Script installable/time triggers: https://developers.google.com/apps-script/guides/triggers/installable
- GmailApp reference (search, moveThreadsToTrash): https://developers.google.com/apps-script/reference/gmail/gmail-app