gh_UserManager/docs/MAILBOX.md
bermooda-company 1f995295a6 last changes
2026-10-22 16:58:51 +03:30

3.3 KiB

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)

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"
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=<shared secret with provider>

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.