CommerceOS docsmenu

Build

Email & sender identity

Store transactional mail — order confirmations, refunds, shipping updates — can send from the merchant’s own domain. The merchant adds DNS records; the platform sends on their behalf. Nobody ever configures SMTP credentials.

Two sending tiers

Platform mail(billing, staff sign-in codes, admin notices) always sends from the platform’s own domain. Store mail(a store → its customers) sends from the store’s verified sending domain — e.g. orders@yourbrand.com — and falls back to a platform-branded sender (“Aurora Threads” <no-reply@…>) until a domain is verified. Customer replies go to the store’s reply-to address either way.

Register a sending domain

In the admin this is Email in the sidebar; over the API it is one call. The response carries every DNS record the merchant must create at their registrar: three DKIM CNAMEs (signature alignment) plus an MX + SPF TXT on the mail.subdomain (envelope alignment) — together they make the mail pass DMARC as the merchant’s own.

wire · register + the records to create
▸ POST /email/sending-domain▸ authorization: Bearer <staff session token>     # admin surface, owner/admin role{ "domain": "yourbrand.com", "fromLocalPart": "orders" } ◂ 201{  "domain": "yourbrand.com",  "status": "pending",  "fromLocalPart": "orders",  "dnsRecords": [    { "type": "CNAME", "name": "<token1>._domainkey.yourbrand.com", "value": "<token1>.dkim.amazonses.com" },    { "type": "CNAME", "name": "<token2>._domainkey.yourbrand.com", "value": "<token2>.dkim.amazonses.com" },    { "type": "CNAME", "name": "<token3>._domainkey.yourbrand.com", "value": "<token3>.dkim.amazonses.com" },    { "type": "MX",  "name": "mail.yourbrand.com", "value": "feedback-smtp.ap-south-1.amazonses.com", "priority": 10 },    { "type": "TXT", "name": "mail.yourbrand.com", "value": "\"v=spf1 include:amazonses.com ~all\"" }  ]}

Verification lifecycle

A domain is pending until the provider observes the DNS records — the platform polls every few minutes (and on demand via verify), so there is nothing to babysit. DNS propagation typically takes minutes, occasionally up to an hour. failed means the provider gave up; fix the records and verify again. The moment a domain is verified, every subsequent customer email sends from it — no restart, no re-save.

wire · what customers see, before and after
▸ GET /email/sender▸ authorization: Bearer <staff session token> ◂ 200                                  # before verification{  "mode": "platform-fallback",  "effectiveFrom": "no-reply@<platform domain>",  "effectiveFromName": "Aurora Threads",  "replyTo": "help@yourbrand.com",  "domain": { "domain": "yourbrand.com", "status": "pending", … }} ◂ 200                                  # after DNS verifies{  "mode": "custom-domain",  "effectiveFrom": "orders@yourbrand.com",  "effectiveFromName": "Aurora Threads",}

Endpoints

Admin API (staff session)TypeDescription
GET /email/senderreadEffective sender state: exactly what customers will see on this store’s mail.
POST /email/sending-domainwriteRegister the store’s sending domain; returns the DNS records to create. One domain per store.
POST /email/sending-domain/verifywriteAsk the provider to check DNS now instead of waiting for the sweep.
DELETE /email/sending-domainwriteRemove the domain — mail reverts to the platform fallback sender.

A domain authorizes exactly one store. Registration is globally unique and tenant-isolated — another store attempting to register (or mail as) your domain is rejected at the API, by the database constraint, and by row-level security underneath it.

Reply-to

Set the store’s reply-to address in admin → Email (or PUT /settings with replyToEmail). It rides every customer email, including fallback-sender mail — so replies reach the merchant even before a domain is verified.