M365 Email Reports

Email · Storage · Apps · Activity — Microsoft 365 tenant analytics

Self-hosted reporting platform that pulls per-user email activity, app usage and mailbox storage metrics from the Microsoft Graph Reports API and surfaces them in a fast, filterable dashboard with department scoping, drill-downs and exports to Excel / CSV.

What's included
Reports
  • Daily activity — send / receive / read per user per day
  • User drill-down — full history + chart per mailbox
  • Department comparison — side-by-side bar & line charts
  • Inactive users — configurable threshold
  • Email app usage — Outlook / Mobile / Web / IMAP / POP adoption
  • Mailbox storage — usage, quota warnings, item counts
Platform
  • Local user accounts (no Microsoft sign-in required)
  • Roles: Reports (scoped to assigned departments) and SuperAdmin
  • Departments map mailboxes → users for granular access control
  • Background ingestion via Hangfire (in-process)
  • Idempotent upserts — safe to re-run any job
  • CSV + Excel export on every report
  • Audit log of all admin changes
How it works
  1. Hangfire (embedded inside the Web app) schedules three background jobs:
    • ingest-email-activity — per-day per-user send/receive/read (every 4h)
    • ingest-email-app-usage — per-day per-user app usage (every 6h)
    • ingest-mailbox-usage — mailbox storage snapshot (daily)
  2. Each job calls Microsoft Graph (v1.0/reports/...) with a Client Secret or certificate from the App Registration configured at /Admin/Setup.
  3. Microsoft returns CSV; the service parses it and upserts into SQL Server by composite key (ReportDate, UserPrincipalName, TenantId).
  4. The Razor Pages UI queries SQL directly — no live calls to Graph from the browser.
  5. Visibility is filtered per role: SuperAdmin sees the whole tenant, Reports users see only the mailboxes assigned to their departments.
Security
  • Local accounts only, PBKDF2 password hashes via ASP.NET PasswordHasher<T>
  • Cookie auth with HttpOnly + sliding expiration (8h normal, 14d "remember me")
  • Forced password change on first login
  • Graph backend uses app-only auth (Client Secret or Certificate)
  • Only one Graph permission required: Reports.Read.All
  • No mailbox content is ever read — metric counts only
Credits

Designed and built by Juan Guzman.
Powered by ASP.NET Core 8 (Razor Pages), EF Core, Hangfire, ClosedXML and Microsoft Graph.

Runtime
App version1.0.0.0
.NET runtime8.0.27
ServerIISSVR1
Server time (UTC)2026-06-10 04:54:58