CORPORATE & HR Internal tool Launched 2025

Corporate Mailbox Cleanup Tool for 600 Employees

Corporate mailboxes across an organisation of six hundred people were being eaten by automated notifications: task tracker alerts, system messages from internal services, chat and intranet digests. We built a console tool over the Microsoft Graph API that mirrors mailbox metadata locally, lets an administrator search it by sender, subject, recipient, folder and date, shows exactly what matched, and deletes it in batches — writing every message to disk as an .eml file first.

600
mailboxes handled from one console
Every deletion
saved as .eml before it happens
Local index
search instead of live API queries

The problem we were asked to solve

Mailbox bloat in a large tenant is rarely caused by people writing to each other. It is caused by machines: a task tracker that emails on every comment, an ERP that sends a message per document, a chat platform that mails a digest nobody opens. The volume accumulates for years, storage quotas fill, and search inside the mailbox stops being usable. Cleaning it centrally is easy to do badly. The Graph API will happily delete anything an application permission allows, and a mistyped filter across six hundred mailboxes is not a mistake anyone recovers from by hand. Doing it interactively is worse in a different way: the same search, run against the live API mailbox after mailbox, is slow, hits throttling, and gives the administrator no chance to look at the result set as a whole before acting on it. What was needed was something closer to a database session than to a mail client — see the matches, count them, then decide.

What we built

01

Local mirror of mailbox metadata

The tool syncs message metadata — sender, recipients, subject, folder, received date, identifiers — into a local SQLite index, page by page, resuming from what it already has rather than re-reading the mailbox. Every subsequent search runs against that index, so a query over years of mail is instant and costs the API nothing.

02

Search before you delete

Filters combine freely: subject contains, sender contains, recipient contains, folder, date from and date to. The tool prints the matched messages with their dates, addresses and subjects and reports the count first. Deletion is a separate, explicitly confirmed step — the administrator sees the exact set before anything is touched.

03

Backup as .eml before deletion

With backup enabled, each message is downloaded in full and written to disk as an .eml file under a folder structure of mailbox and mail folder, named by its received timestamp, before the delete call is issued. A message whose backup fails is skipped rather than deleted, so nothing leaves the tenant without a copy on disk that any mail client can reopen.

04

Batched deletion against Graph

Deletions go out in batches of twenty through the Graph batch endpoint rather than one request per message, and the per-message results are read back individually: successes are removed from the local index, failures are reported with their reason and left in place. Progress is printed as it goes, so a run over tens of thousands of messages can be watched and interrupted.

05

Traffic report to find the noise

Before deciding what to clean, an administrator can ask for a day-by-day sent and received count for any correspondent in a mailbox over a date range. It is what turns a vague complaint about a full mailbox into a named sender and a period — the notification service, the reporting robot, the digest — which is then the filter for the cleanup itself.

06

Companion exporter for analysis

A second service walks the same tenant with the list of active users, recurses through their folders with system folders excluded, and writes messages into PostgreSQL: direction, folder path, identifiers, addresses, subject, the body cleaned of signatures and reply chains, and attachment names with sizes. Graph throttling is handled with backoff that honours Retry-After, so a full-tenant export runs unattended.

Go Microsoft Graph API Microsoft Entra ID (application permissions, admin consent) SQLite PostgreSQL Docker
Console session: a mailbox and folder selected, the local index refreshed, a search by sender and date returning 4 812 matches listed before anything happens, then each message written to disk as an .eml file and deleted in batches, with a day-by-day traffic report and the backup directory alongside
One cleanup session end to end — search, review, back up, delete. Reproduced with invented mailboxes, senders and figures.
Tenant export run: eight workers walking 600 active users' folders, throttled requests retried with backoff, one unprovisioned mailbox skipped, and a SQL query over the exported messages ranking the automated senders that fill the most mailboxes
The read-only exporter that finds which senders fill the mailboxes. Reproduced with invented mailboxes, senders and figures.

What changed for the client

Mailbox cleanup became a reviewable operation rather than a leap of faith. An administrator can name what is filling a mailbox from the traffic report, search the local index to see the exact set of messages, and delete them in batches with an .eml copy of every message on disk first. The tool is used internally across an organisation of roughly six hundred employees, and the companion exporter puts the same mail into PostgreSQL when the mail itself needs to be analysed rather than removed.

  • One console handles mailbox cleanup across an organisation of roughly 600 employees, without asking employees to clean up after themselves.
  • Searching a local index instead of the live API makes queries over years of mail instant and keeps the run away from API throttling.
  • Nothing is deleted before it is listed and counted, and nothing is deleted before an .eml copy is written to disk.
  • A message whose backup fails is skipped rather than deleted, so a failed download can never turn into a lost email.
  • Batched deletion with per-message results means a partial failure is reported and retried, not silently swallowed.
  • The day-by-day traffic report turns a full mailbox into a named sender and a date range — which is the filter the cleanup then uses.

Want similar results?

Tell us what the process looks like today and we will tell you what can be automated — and what should not be.

LET'S TALK