Python — Automation Systems

AI-Powered Email Processing Automation

Direct answer

The production pattern I use is a three-stage pipeline: ingest mail through IMAP or an inbound-parse webhook, classify and extract structured fields with an LLM held to a strict JSON contract, then route each message into your ticketing system or CRM — with anything below a confidence threshold falling into a human review queue. The LLM replaces the brittle keyword rules that used to break weekly; the deduplication, retries, and human fallback around it are what make the system trustworthy.

Shared inboxes are where operations go to die: orders, invoices, support requests, and spam all land in one place, and a human triages them by hand every morning. This post covers the architecture I use to automate that triage with an LLM in the middle — including the unglamorous plumbing that decides whether the system is production-grade or a demo.

Key facts, with sources

  • Grand View Research sized the robotic process automation market at $4.68 billion in 2025 and projects it to reach $35.84 billion by 2033, a 29.0% compound annual growth rate. (Grand View Research)
  • Gartner's worldwide market share analysis found RPA software generated about $3.8 billion in revenue in 2024, an 18% year-over-year increase, even as generative AI and agentic tools slowed the segment's growth rate. (Gartner)
  • TestGuild's 2025 survey put Playwright at 45.1% adoption among QA professionals with a 94% retention rate, versus 22% and declining for Selenium. (TestDino)
  • Playwright job postings grew 180% year over year in 2025, making it the fastest-growing category in QA automation hiring. (TestDino)
  • Playwright leads browser automation tooling with roughly 30 million weekly npm downloads compared to Cypress at 6.5 million, after growing from about 1.2 million weekly downloads in January 2022. (Tech Insider)

Why rule-based email parsing keeps breaking

Before LLMs, email automation meant regex and keyword rules, and I've audited enough of these systems to know how they age: every sender format change adds another rule, forwarded chains and reply quoting defeat the parser, HTML-only messages need their own path, and after a couple of years nobody dares touch the rule file. The core problem is that email is adversarially unstructured — written by humans and by hundreds of different systems, none of which agreed on a format.

An LLM handles that variety natively. It reads a forwarded, half-quoted, typo-ridden message the same way a human triager does. What it doesn't give you for free is consistency, idempotency, or safety — those come from the pipeline around it.

Ingestion and deduplication before any AI

I persist the raw message first and process it asynchronously — never inline with the fetch. Whether mail arrives via IMAP polling or an inbound-parse webhook, each message gets written to storage keyed on its Message-ID header, which doubles as the idempotency key: if the poller sees the same message twice, or the webhook retries, nothing downstream runs again.

Processing happens off a queue. That decouples ingest speed from LLM latency, lets me retry classification without re-fetching mail, and gives me a replay path: when I improve the prompt, I can rerun the last month of raw messages through the new version and diff the results before deploying.

Classification with a strict JSON contract

The LLM call itself is small: a fixed label set, a JSON-only response format, the body truncated to a sane length, and low temperature. I keep the category list short and mutually exclusive — five to eight labels is usually the sweet spot; beyond that, accuracy drops and so does anyone's ability to reason about the routing table. A few worked examples of genuinely ambiguous messages in the prompt buy more accuracy than any amount of instruction-tuning prose.

Every response gets validated before use. If the JSON doesn't parse or the category isn't in the allowed set, that's a processing failure that retries once and then routes to the human queue — never a guess.

LLM email classification with a JSON contract
import json

from openai import OpenAI

client = OpenAI()

SYSTEM = """Classify the email and return only JSON with keys:
category: one of invoice | order | support | sales | spam | other
urgency: one of low | normal | high
summary: one sentence
confidence: number between 0 and 1"""

ALLOWED = {"invoice", "order", "support", "sales", "spam", "other"}


def classify_email(subject: str, body: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,
        response_format={"type": "json_object"},
        messages=[
            {"role": "system", "content": SYSTEM},
            {"role": "user", "content": f"Subject: {subject}\n\n{body[:4000]}"},
        ],
    )
    result = json.loads(response.choices[0].message.content)
    if result.get("category") not in ALLOWED:
        raise ValueError(f"invalid category: {result.get('category')}")
    return result

Confidence thresholds and the human queue

The confidence score an LLM reports about itself is a heuristic, not a calibrated probability — but it's still useful triage signal. I combine it with the stakes of the category: a low-confidence spam call costs nothing if wrong, while anything classified as an invoice or a legal notice goes to human review unless confidence is high, because the cost of misrouting is asymmetric.

The human queue is a feature, not a failure. Reviewers correct the label in one click, and every correction gets logged alongside the model's original output. That log becomes my eval set: before any prompt or model change ships, it has to match or beat the current version against the accumulated corrections.

Routing with an audit trail you can replay

The final stage writes into downstream systems — a ticket, a CRM activity, an accounts-payable queue — and every write is idempotent, keyed on the Message-ID, so a retried job never creates a duplicate ticket. Alongside the routed record I store the original message reference, the full model output, and the prompt version that produced it.

That audit trail earns its keep the first time someone asks why a message went where it went. It also makes the system improvable: with raw inputs and versioned outputs preserved, I can measure exactly what a new prompt changes across historical traffic instead of guessing. Email automation without replayability is a system you can only tune blind.

When to hire senior help

Bring in senior help when automations move from convenience scripts to business-critical paths, such as billing, order processing, or compliance reporting, where a silent failure has real financial consequences. An experienced engineer will add the monitoring, idempotency, and credential management that separates durable automation systems from fragile scripts. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.

Bottom line

Dhairya Senjaliya ships Python — Automation Systems projects worldwide — book a scoping call to discuss your specific situation.

Common pitfalls to avoid

  • Automating a broken manual process as-is instead of mapping and simplifying it first, which just makes the inefficiency run faster
  • Building UI screen-scraping bots against internal apps that expose APIs, so every minor UI update breaks the automation
  • Running unattended automations with no monitoring or alerting, so a silently failing nightly job goes unnoticed until month-end numbers are wrong
  • Hardcoding credentials in scripts and running automations under a personal employee account, creating security exposure and a single point of failure when that person leaves

Frequently asked questions

Can AI automatically sort and route business emails?

Yes, reliably — with the right architecture. An LLM classifying into a small fixed label set, constrained to JSON output and validated before use, handles the messy variety of real email far better than keyword rules. The key is a confidence threshold that routes uncertain or high-stakes messages to a human review queue instead of guessing, plus deduplication so nothing gets processed twice.

What happens when the AI misclassifies an email?

Design for it rather than pretend it won't happen. Low-confidence results and high-stakes categories like invoices or legal notices go to a human queue, corrections are one click, and every correction is logged with the model's original output. That correction log becomes an evaluation set, so each prompt or model change is tested against real past mistakes before it ships.

Should email automation use IMAP polling or webhooks?

Webhooks from an inbound-parse service are cleaner when you control the address — mail arrives as a structured HTTP request with no polling loop. IMAP polling is the pragmatic choice when the mailbox already exists on standard business email and nobody wants to change MX records. Either way, persist the raw message keyed on its Message-ID and process asynchronously from a queue.

Should we buy an RPA platform or build custom Python automation?

RPA platforms (a $4.68 billion market in 2025 per Grand View Research) suit non-technical teams automating legacy GUI workflows with vendor support. Custom Python automation is cheaper at scale, version-controllable, and testable, but requires engineering ownership. Teams with any engineering capacity usually get more durable results from Python plus APIs than from licensed bot seats.

What ROI should we expect from automation?

Returns depend on frequency times manual effort times error cost of the process automated; high-volume, rule-based back-office tasks recoup build cost fastest. The 18% annual growth Gartner measured in RPA spending reflects that companies consistently find positive returns, but the biggest wins come from processes measured first, automated second.

How do we stop automations from constantly breaking?

Prefer API integrations over UI automation wherever possible, add monitoring with alerts on both failures and anomalous outputs, and treat automation code like production software with version control and tests. Modern tooling like Playwright with auto-waiting selectors also breaks far less than legacy screen-position scripts.

Bottom line: Dhairya Senjaliya ships Python — Automation Systems projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.

Sources

Related guides

Keep up with new guides

New deep-dive guides on React Native, Python, and AI ship regularly. Subscribe via RSS or follow on LinkedIn.

Want help implementing this?

30-minute scoping call · Clear milestones · Senior engineer ownership