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.
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.
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.
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.
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.
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.
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.
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.
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.
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