DEV Community

TiltedLunar123
TiltedLunar123

Posted on

Gmail's Trash gives back your emails, not your undo

Deleting mail in bulk is easy. You run a search and hit delete on what comes back, over and over; the whole loop is about forty lines of code.

Undoing this operation turns out to be trickier, and I made a misstep initially because I thought Gmail's Trash folder was already my undo button.

It isn't.

Trash gives back the emails, not the operation

Trash just holds emails for 30 days. So technically nothing is lost, since the messages are still there waiting to be restored.

The issue lies with what you're trying to restore. If you run a cleanup that touches four thousand conversations through twelve different searches, your Trash ends up holding all of them mixed in with whatever you deleted last Tuesday and the thread you dropped on purpose this morning. Nothing marks where one run ends and another begins.

You can restore an email. Can you restore that run? No. And users usually want more than one message back; they want their last five minutes undone.

That gap is the actual feature, because Gmail has no concept of the batch you just ran.

What the log needs to record

  • The exact search query used
  • A list of ids actually acted on, not those matched
  • A timestamp for when the run happened
  • The point at which restoring stops working

The third and fourth items might seem redundant, but they're crucial. The timestamp is when it happened; the expiry is when the promise runs out, and those two are only the same thing if you assume the retention window never changes.

The distinction between "matched" and "acted on" matters because a run that dies mid-way results in different sets of matched and deleted emails. A log based solely on intent could offer to restore mail that wasn't removed, creating confusion or worse, teaching users the undo button is unreliable.

It has to live on the machine

The extension makes no network calls; it's a deliberate design choice, and it means there is no server-side place to keep a log. The data is stored locally in browser storage, which comes with its own challenges.

The first limit is size. Storing ids for tens of thousands of messages across multiple runs isn't free, and there is no point keeping an entry past the window where it can still do something.

The second one bit me. chrome.storage.local.set replaces the value at a key instead of merging into it, so writing the log for run two silently loses run one. Testing never caught it, because you almost always test the most recent action and that one is always correct. I found it while checking something else entirely.

So the write path has to read the key first and merge into it. Obvious, once you have lost data that way.

Expiry has to be visible

An undo entry outside the retention window is worse than no entry at all; it advertises a capability that won't work at the exact moment somebody needs it. So the log shows when each entry stops working, and anything past that point comes off the list.

It reads like a small detail next to the deletion engine. It is the difference between a guarantee and a suggestion.

The cheaper half is not deleting

All of this is about recovery. The better move is not needing it.

Dry runs are the key here: same query, same counts, nothing actually deleted. Most of the value of an undo system is captured by showing someone the number before they commit to it. The classic disaster isn't deleting the right things and changing your mind; it's thinking a search meant something else.

The same logic applies to protecting starred and important mail automatically. That protection belongs inside the query you count with, not applied as a filter after fetching results. If you exclude items after fetching, the number shown to the user came from a different set than the one the delete call sees, and any retry path can quietly act on the wrong list. The count and the action have to be reading the same thing.

The limit, stated plainly

None of this is a backup. Once Gmail's window closes, a recovery log is just a list of ids for mail that no longer exists. It's a 30 day guarantee, and it should be described as exactly that rather than dressed up as safety.

If you want the tool, it's Gmail One-Click Cleaner on the Chrome Web Store. It runs locally and its source is on GitHub; bulk cleanup is free.

The engine took a weekend. The undo took considerably longer, and it's the part I would keep.

Top comments (0)