# Mailbox (ali@jobid.ir) — full personal email Additive module. No existing model touched. ## Endpoints (v1) - `GET/PATCH /api/v1/mailbox/me/` — auto-creates `user@jobid.ir` on first visit - `GET /api/v1/mailbox/folders/` — inbox/sent/drafts/spam/trash + unread counts - `GET /api/v1/mailbox/messages/?folder=inbox&search=&seen=&flagged=` - `GET /api/v1/mailbox/messages/:id/` — marks seen - `POST /api/v1/mailbox/messages/` — compose+send (rate-limited, audited) - `POST /api/v1/mailbox/messages/draft/` — save draft - `POST /api/v1/mailbox/messages/:id/read|unread|flag|move/` - `DELETE /api/v1/mailbox/messages/:id/` — trash first, then hard delete - `POST /api/v1/mailbox/webhooks/inbound/` — provider inbound (HMAC, no auth) - `POST /api/v1/mailbox/messages/:id/reply/` — reply with quote - `GET /api/v1/mailbox/messages/export/` — full JSON export (max 5000) - `CRUD /api/v1/mailbox/filters/` — auto-rules (from/subject → flag/read/spam/move) - `CRUD /api/v1/mailbox/templates/` — compose templates (3 defaults seeded) - `GET /api/v1/mailbox/attachments/:id/` — file download (use `?meta=1` for JSON) - `GET /api/v1/mailbox/me/unread/` — global unread count (header badge, 60s poll) - `GET /api/v1/mailbox/messages/:id/thread/` — full conversation - `POST /api/v1/mailbox/messages/:id/save/` — autosave draft fields ## Frontend - `/mail` — Gmail-like: folders sidebar + unread badge + quota bar, search, read view, compose modal (templates + send-later + attachments + autosave drafts), thread/conversation panel, star/spam/trash, reply/forward, export button, filters manager, attachment download. - Global unread badge (`components/mail-badge.tsx`): `/account` sidebar + `/passport` header + `/mail` header, polling every 60s. ## Scheduled send `POST /messages/` accepts `scheduled_at` (ISO). Message stays `scheduled` until `python manage.py send_queued_mail` runs — wire it to cron/beat every minute in production. ## Internal delivery (Phase 4) Recipients matching a `Mailbox.address` are delivered **internally** (direct inbox insert + notification) without touching SMTP — free, instant, and works before DNS is even set. External recipients go through the provider. Audit records both lists. Signatures: `PATCH /mailbox/me/` sets `display_name` + `signature`; the signature is auto-appended to every outbound body. Settings UI lives in the `/mail` sidebar. ## Provider wiring (production) ```dns jobid.ir. MX 10 mail-provider-host. jobid.ir. TXT "v=spf1 include:provider ~all" selector._domainkey.jobid.ir. TXT "v=DKIM1; k=rsa; p=..." _dmarc.jobid.ir. TXT "v=DMARC1; p=none; rua=mailto:dmarc@jobid.ir" ``` ```env EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend EMAIL_HOST=smtp.provider.example EMAIL_PORT=587 EMAIL_USE_TLS=1 EMAIL_HOST_USER=postmaster@jobid.ir EMAIL_HOST_PASSWORD=... MAIL_INBOUND_SECRET= ``` Provider forwards inbound mail to `POST /api/v1/mailbox/webhooks/inbound/` with `X-Mail-Signature: HMAC_SHA256(body)`. Start DMARC at `p=none`, then `quarantine`, then `reject`. ## Limits (env-tunable) - `MAIL_DAILY_SEND_LIMIT` (default 200), max 50 recipients/message - `MAIL_MAX_ATTACH_MB` (default 10), `.exe/.bat/.ps1/...` blocked - Quota `quota_mb` per mailbox (default 1024MB), bodies on Postgres, files on object storage.