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
-
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)
-
Each job calls Microsoft Graph (
v1.0/reports/...) with a Client Secret or certificate from the App Registration configured at/Admin/Setup. -
Microsoft returns CSV; the service parses it and upserts into SQL Server by
composite key
(ReportDate, UserPrincipalName, TenantId). - The Razor Pages UI queries SQL directly — no live calls to Graph from the browser.
- 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 version | 1.0.0.0 |
|---|---|
| .NET runtime | 8.0.27 |
| Server | IISSVR1 |
| Server time (UTC) | 2026-06-10 04:54:58 |