ReferenceAsk
Remy Reference/Architecture/Architecture/Email
29Architecture

Email

How apps send through Amazon SES with a tenant per app and their own domains, and how inbound mail arrives at the platform's SMTP server and becomes a method invocation.

Apps send email and receive it. Outbound mail goes through Amazon SES with a tenant per app, so one app's reputation never touches another's, and customers can send from their own domains. Inbound mail arrives at an SMTP server the platform runs and becomes a method invocation. This chapter covers both directions.


#Outbound

One SES tenant per app. SES tenants partition sending reputation and suppression. When an app first sends, the platform creates its tenant, associates it with the shared configuration set, and records the association durably in the platform database so the one-time provisioning is never repeated. A hard bounce for one app suppresses that address for that app alone; suppression is deliberately scoped at the tenant, never at the configuration set, so no app's bounce blocks an address for every other app.

Sending domains. By default an app sends from the platform apex, whose identity is verified with DKIM. A workspace can add its own domain, at the app level or shared across its apps. The platform creates the SES identity, hands the customer the DKIM CNAME records to paste at their DNS provider, mirrors the verification state, and switches sending to the custom domain once verified.

The send path. A method calls the SDK to send; the platform accepts the send, records a batch row, stores the payload compressed in the workspace's region, and enqueues chunks of recipients on the email-send queue. Workers drain the queue and call SES, bounded per recipient chunk so a large fan-out never blocks a request. Per-message delivery events flow back from SES through a dedicated queue and are matched to the batch, so the dashboard shows deliveries, bounces, and complaints per message. Reputation notifications arrive on their own queue.

Suppression and unsubscribe. Every app carries a suppression list, fed by bounces, complaints, and unsubscribes, and honored before a send. Unsubscribe links resolve on the platform so they work without app code.


#Inbound

The listener. The mail-inbound role runs an SMTP server behind an internet-facing Network Load Balancer that targets the pods directly and preserves the client address. The public MX record for the platform's mail apex points at it.

Resolution. The server takes the recipient address, matches the domain to a platform apex, and treats the single subdomain label as the app. Only single-label subdomains of a platform apex resolve; reserved labels are refused; anything else is rejected during the SMTP conversation.

Dispatch. The message is parsed, and the app's manifest names the method its email interface runs. The run is a system invocation on a disposable sandbox with the parsed message as input, so a mailbox can drive a workflow without the app running a mail server.

What This Gives an App
Sending from its own domain with DKIM, without an SES account of its own.
Reputation and suppression that are its alone.
Delivery tracking per message in the dashboard.
An inbound address that is a method call, with nothing to host.
DiagramFIG. 29 — EMAIL
sender's MTArecipientsA method sendsthrough the SDKone call, many recipientsThe platform acceptsbatch row · payload in regionchunks to the send queueSend workersdrain the queue in chunkscall SES per chunkAmazon SESone tenant per appidentity: apex or your domain (DKIM)Delivery trackingSES events, matched per messagedeliveries, bounces, complaintsPublic MX and NLBSMTP · client IP preservedtargets the pods directlyMail-inbound roleresolves <label>.<apex> = the appsingle-label subdomains onlyEmail interfacesystem · disposable sandboxparsed message as inputOUTBOUND · SENDINBOUND · RECEIVEchecked against the app's suppression list before send; unsubscribe resolves on the platformevents and reputation queuesthe email door · Fig 27
role · servicesend and receive flowdelivery to recipientssender / recipients (off-figure)
Two directions, one platform. Outbound: a method sends through the SDK, and the platform accepts the send, records a batch row, stores the payload in the workspace’s region, and chunks the recipients onto a send queue that workers drain and hand to Amazon SES. SES keeps one tenant per app, so one app’s reputation and suppression never touch another’s, and it sends from the platform apex or the workspace’s own verified domain, each with DKIM. Delivery events come back matched per message, and the dashboard shows deliveries, bounces, and complaints; the send is checked against the app’s suppression list first, and unsubscribe links resolve on the platform. Inbound: a sender’s mail reaches the public MX and a Network Load Balancer that preserves the client address, the mail-inbound role accepts it over SMTP and resolves the single subdomain label to the app, and the app’s email-interface method runs as the system user on a disposable sandbox with the parsed message as input. No trust boundary is drawn here, so there is no crimson.

Figure 29, "Email": two directions, two lanes, both left to right. Outbound (top): a method sends through the SDK; the platform accepts, records a batch row, stores the payload in the workspace's region, and chunks the recipients onto a send queue; send workers drain the queue and call Amazon SES, drawn as the heavy node (one tenant per app; identity = platform apex or the workspace's verified domain, with DKIM); SES delivers out to recipients as a dashed egress to the off-figure world. Delivery tracking hangs off SES: events and reputation queues, matched per message into deliveries, bounces, and complaints for the dashboard. A note between the row and its tracking records that the send is checked against the app's suppression list first, and that unsubscribe resolves on the platform. Inbound (bottom): a sender's MTA reaches the public MX and a Network Load Balancer that preserves the client address; the mail-inbound role accepts over SMTP and resolves the single subdomain label to the app; the email interface runs as the system user on a disposable sandbox with the parsed message as input. A cross-reference points to the email door in Figure 27. No trust boundary is drawn in this figure, so there is no crimson.