Email processing services

Introduction#

Email stack overview: EmailNoticeService for general notices, PlacementService for offers, formatters that turn structured data into sendable text. How main.py runs them in order.

Project structure#

The email processing system is organized around modular services and clients:

  • Services: EmailNoticeService, PlacementService, NoticeFormatterService, PlacementNotificationFormatter, PlacementPolicyService
  • Clients: GoogleGroupsClient for email ingestion
  • Database: DatabaseService for persistence
  • Orchestration: main.py coordinates email processing and integrates with the broader notification system

Core components#

  • EmailNoticeService: LLM-driven classification and extraction of general notices (announcements, job postings, webinars, hackathons, shortlistings, reminders, internship NOCs). Integrates with NoticeFormatterService for standardized formatting and PlacementPolicyService for policy updates.
  • PlacementService: Keyword-based classification plus LLM extraction for final placement offers, with privacy sanitization and structured validation.
  • NoticeFormatterService: LLM-based notice formatting pipeline (text extraction, classification, fuzzy matching, structured extraction, and message formatting) for general notices.
  • PlacementNotificationFormatter: Creates notification-ready documents for placement events (new offers and updates).
  • PlacementPolicyService: Manages placement policy documents (Markdown, TOC generation, year extraction, CRUD).
  • GoogleGroupsClient: IMAP-based email retrieval and forwarded metadata extraction.
  • DatabaseService: MongoDB operations for notices, jobs, placement offers, policies, and user management.

Architecture overview#

The system orchestrates email processing through a unified command that:

  1. Fetches unread email IDs
  2. Attempts PlacementService classification/extraction
  3. Falls back to EmailNoticeService for general notices
  4. Persists results to MongoDB
  5. Generates placement notifications via PlacementNotificationFormatter

Detailed component analysis#

EmailNoticeService#

  • Purpose: Classify and extract general notices from Google Groups emails using LLM prompts and LangGraph.
  • Key features:
  • LLM-based classification (no keyword filtering) with a dedicated prompt template
  • Structured extraction into ExtractedNotice with detailed fields (job postings, webinars, hackathons, shortlistings, internship NOCs, reminders)
  • Retry logic with validation and error handling
  • Integration with NoticeFormatterService for standardized formatting
  • Special handling for placement policy updates via PlacementPolicyService
  • Creation of NoticeDocument for database storage and Telegram formatting
  • Processing pipeline:
  • Classify -> Extract -> Validate -> Display
  • JSON extraction from LLM responses with reliable error handling
  • Advanced policy extraction with a secondary prompt for policy updates

PlacementService#

  • Purpose: Extract final placement offers from emails using keyword-based classification and LLM extraction.
  • Key features:
  • Keyword scoring for placement-related signals, company indicators, and negative filters
  • LLM extraction with structured validation and retry logic
  • Privacy sanitization to remove headers and forwarded metadata
  • Improved validation (roles, students, packages)
  • Integration with PlacementNotificationFormatter for notification creation
  • Processing pipeline:
  • Classify (keyword scoring) -> Extract (LLM) -> Validate & Improve -> Sanitize Privacy -> Display

NoticeFormatterService#

  • Purpose: Standardize and format notices into notification-ready content using LLM prompts and LangGraph.
  • Key features:
  • Text extraction from HTML content
  • Single-label classification (update, shortlisting, announcement, hackathon, webinar, job posting)
  • Fuzzy company name matching against job listings
  • Structured extraction based on category
  • Formatting into Telegram-ready messages with consistent styles and deadlines
  • Processing pipeline:
  • Extract Text -> Classify -> Match Job -> Enrich Matched Job -> Extract Info -> Format Message

PlacementNotificationFormatter#

  • Purpose: Create notification-ready documents for placement events (new offers and updates).
  • Key features:
  • Role breakdown and counts
  • Package formatting helpers
  • New offer and update offer formatting
  • Integration with DatabaseService for persistence
  • Processing:
  • NewOfferEvent -> format_new_offer_notice
  • UpdateOfferEvent -> format_update_offer_notice
  • process_events orchestrates multiple events and saves to DB

PlacementPolicyService#

  • Purpose: Manage placement policy documents (Markdown, TOC, year extraction, CRUD).
  • Key features:
  • Advanced LLM extraction for policy updates with strict JSON schema
  • Slug generation for GitHub-style TOC IDs
  • Year and update date extraction
  • Upsert operations for MongoDB
  • Processing:
  • process_policy_email orchestrates extraction and persistence

GoogleGroupsClient#

  • Purpose: Decoupled email ingestion for Google Groups using IMAP.
  • Key features:
  • Connect/disconnect management
  • Fetch unread IDs and emails
  • Forwarded date and sender extraction
  • Mark as read/unread

DatabaseService#

  • Purpose: Centralized MongoDB operations for notices, jobs, placement offers, policies, and users.
  • Key features:
  • Notice CRUD and stats
  • Job upsert and retrieval
  • Placement offers save with merge logic and event emission
  • Official placement data save with content hashing
  • Policies CRUD and retrieval
  • Users management

Dependency analysis#

  • EmailNoticeService depends on:
  • GoogleGroupsClient for email ingestion
  • NoticeFormatterService for standardized formatting
  • PlacementPolicyService for policy update handling
  • DatabaseService for persistence
  • PlacementService depends on:
  • DatabaseService for saving offers and emitting events
  • PlacementNotificationFormatter for notification creation
  • NoticeFormatterService depends on:
  • LLM prompts and LangGraph for classification and extraction
  • DatabaseService for job matching and enrichment
  • PlacementNotificationFormatter depends on:
  • DatabaseService for saving notices
  • GoogleGroupsClient is a standalone email ingestion client
  • DatabaseService is a central persistence layer

Performance considerations#

  • LLM calls: Both EmailNoticeService and PlacementService use LLMs for extraction. Consider rate limits and cost by batching and caching where appropriate.
  • Retry logic: PlacementService includes retry attempts for validation failures; EmailNoticeService retries on extraction errors up to a limit.
  • IMAP operations: Fetching and parsing emails can be I/O bound; process emails sequentially to avoid connection thrashing.
  • Database writes: Batch operations where possible; PlacementService’s save_placement_offers merges updates efficiently.
  • Formatting: NoticeFormatterService performs multiple LLM calls; cache or reuse results when feasible.

[No sources needed since this section provides general guidance]

Troubleshooting guide#

Common issues and resolutions:

  • LLM JSON parsing failures:
  • PlacementService: Validates JSON and retries up to a maximum; check LLM prompt templates and content normalization.
  • EmailNoticeService: Extracts JSON from fenced blocks and retries on validation errors.
  • Email fetching errors:
  • GoogleGroupsClient raises clear exceptions for missing credentials and connection failures; verify environment variables and network connectivity.
  • Privacy sanitization:
  • PlacementService strips headers and forwarded markers; ensure additional_info and package details are sanitized consistently.
  • Database persistence:
  • DatabaseService returns explicit success/error tuples; inspect returned messages for detailed failure reasons.
  • Daemon mode:
  • Safe printing is disabled in daemon mode; rely on logging to file for visibility.

Conclusion#

Classify, extract, validate, format, persist. The split keeps MongoDB writes and notification delivery boring in a good way. main.py shows how mixed mail sources land in one place.