Not part of the first request. Start this only after Phase A has an answer, and ideally after 30 to 60 days of clean sending on the approved account (the reasoning is in
README.md§1).
Tenant mail means newsletters, mailbox (user-to-user) mail, form notifications and replies, flows/automation mail, chat
mail, tenants' custom sending domains and the shared mail.vlozi.app lane. It is a different kind of sending: the
recipients are chosen by tenants, so the platform needs controls over who may send and to whom, not just over its own
templates.
What must exist first
The in-code switch SES_TENANT_SENDING stays unset until every item below is real, not planned.
| Control | State today | Needed |
|---|---|---|
| Tenant sending approval: a new workspace cannot send campaigns until reviewed; first campaigns manually reviewed | None | Build |
| Consent attestation on import and a ban on purchased lists, enforced in product and in the Terms | Terms mention it; no attestation step | Build |
| Content and URL screening of campaign bodies | None | Build |
| Per-tenant daily caps and warm-up | Mailbox shared lane has caps; newsletter is paced per campaign only | Extend |
| Staff tenant suspend that comms and the gateway both enforce | The reputation breaker pauses sending; no manual ban | Build |
Reputation circuit breaker enforcing (REPUTATION_ENFORCE=true) |
Built; records and warns only | Turn on, after the ops pages are proven |
Bounce-only account suppression, tenant-scoped complaints (ses-account-suppression.mjs) |
Built; not run | Run at this phase |
| Retention and erase job for logs, bodies and webhook payloads | None; the Privacy page promises one | Build, or change the promise |
| Data Processing Addendum for tenants (they are controllers of their subscribers' data) | None | Draft |
| Tenant sending-vetting policy (internal) | None | Draft |
| Unconsented list (Vlozi's own ~503 contacts from the 2026-07-10 bulk import) never mailed | Present and mailable: the import stamped confirmed_at by assertion. The live Anti-spam page already promises no unconsented lists (gap-log G61) |
Decided 2026-10-05: revoke consent, keep the rows (apps/newsletter-service/scripts/revoke-unconsented-import.mjs, dry run first). They become unmailable but stay in the list and can later go through the re-permission flow |
in.vlozi.app DNS and MX, plus INBOUND_DOMAIN |
The name does not exist in DNS (checked 2026-10-05), so reply routing (reply+…) and mailto unsubscribe cannot work. There is no separate "mailto" switch: the mailto List-Unsubscribe entry appears when INBOUND_DOMAIN is set on both comms and newsletter, and apps/communication/.dev.vars says vlozi.app, not in.vlozi.app, so the production value must be read from where it was set |
Create the name, set INBOUND_DOMAIN to it on comms and newsletter, then confirm a campaign's List-Unsubscribe carries the mailto: entry |
| Reject unknown recipients at SMTP time instead of accepting and dropping | The Cloudflare catch-all hands mail to the comms worker (confirmed by the 2026-10-06 role-address tests), which drops an address nobody owns with no bounce. The resolver must first tell "no such mailbox" apart from "lookup failed", or a transient error becomes a permanent rejection | Build (gap-log G11, G12) |
Role addresses on mail.vlozi.app |
Tenant mail is sent from that domain, so mail operators will write to its role addresses. Vlozi's workspace may claim those names there (gap-log G49); the vlozi.app ones already exist |
Create abuse and postmaster on mail.vlozi.app in the Vlozi workspace before tenant sending is enabled |
Options once the controls exist
- A second SES production-access request that describes these controls, referencing the clean record from Phase A.
- A separate AWS account for tenant mail (an AWS Organization member). It limits the blast radius: a tenant problem cannot suspend the account that carries login codes. Costs: a second quota to earn and a second set of identities and DNS.
- Another provider for tenant mail, keeping SES for platform mail. Resend is already integrated for
vlozi.apponly; tenant domains and the shared lane would need provider support and event webhooks.
Decide with real numbers (Phase A volume, bounce and complaint rates, how many tenants are asking for it).
If SES keeps refusing even Phase A
Tenant mail does not have to wait on AWS. Route the tenant lane through another provider and keep SES for platform mail only. That is a separate piece of work (provider selection per lane, webhooks for that provider, domain verification per provider).
When you do write the second request
- Show each control above working, with evidence.
- State the real numbers from the approved account: volume, bounce rate, complaint rate, for how long.
- Describe who may send (vetted workspaces only), what they may send (consented lists, content screened), and what happens when it goes wrong (pause, suspend, suppression, escalation).
- Keep it consistent with the published Terms, Acceptable Use and Anti-Spam policies, which must already say the same.