80 lines
3.3 KiB
Markdown
80 lines
3.3 KiB
Markdown
# 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=<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.
|