outboxthing Get in touch

One outbox · a key per app · one domain per key

One way out for every app's mail.

Every app keeps a mail provider's key, and every one of those keys can send as any domain on the account. outboxthing is one small service in front of the provider: a key per app, each pinned to the one domain it may send from.

Act I

Every app, the whole account.

A booking site sends confirmations, a job tracker sends invites, an agent box mails a login code. Each one signs up, verifies a domain and keeps a key.

01 · A key per app

Each app gets the provider's key.

An API key in the environment, created in the provider's dashboard. It's the only kind of key the provider has: one that can do everything.

mail-provider.example/api-keys
API keys Mail provider
Name smilovice-prod
Permission Full access
Create key
re_7Hk2… created for smilovice.
re_Qm9x… created for applything.

02 · What a key can do

Any key can send as any domain.

The job tracker's key can send a booking confirmation from the booking site's domain. Leak one key, and every domain on the account can be spoofed.

~/applything
$ send --key $APPLYTHING_KEY --from noreply@smilovice5.com
200 · queued
# nothing stopped it

03 · Development

And dev sends real mail.

The same key in a .env file, so a test run emails a real address. Or a second account, a second key, and a second set of DNS records.

~/smilovice
$ mix test
sent: "Your booking" → a.real.guest@example.com
.env: RESEND_API_KEY=re_7Hk2…

That was two apps.

provider keys
3
can send as anyone
1
real mail from dev
1
keys scoped to a domain
0

Here's the same mail, through the outbox.

Act II

The outboxthing way.

One service holds the provider's credentials. Apps hold an outbox key, and the key decides the one domain they may send from.

01 · The keys, declared

A key per app, a domain per key.

One file lists every app, the hash of its key and its domain. It holds nothing secret: the keys themselves live with the apps.

keys.json lines 1–5
[
{"app": "smilovice", "sha256": "9f2c…", "domain": "smilovice5.com"},
{"app": "applything", "sha256": "41ab…", "domain": "applything.com"},
{"app": "llmthing", "sha256": "c07e…", "domain": "llmthing.com"}
]

02 · One call

The app sends; the outbox checks.

One request with the app's key. The sender's domain is checked before the provider is called, so a wrong domain never leaves the box.

~/smilovice
curl -X POST outboxthing.com/send \
-H "Authorization: Bearer $OUTBOX_KEY" \
-d '{"from": "noreply@smilovice5.com",
"to": ["guest@example.com"],
"subject": "Your booking",
"body": "See you on the 12th."}'
200 · id 0102019a… · handed to the provider

03 · Development

Dev mail goes nowhere.

Capture mode logs every message instead of sending it, with no provider credentials on the machine at all. Tests see the mail; nobody receives it.

~/outboxthing
$ OUTBOXTHING_MAILER=capture outboxthing
captured · smilovice → guest@example.com · "Your booking"

04 · The provider, once

One provider, one credential.

SES over plain SMTP, so swapping the provider is a host and a password, not a code change. The credential can send mail and do nothing else.

~
✓ ses:SendRawEmail · nothing else
✓ DKIM, SPF, DMARC on every sending domain

Act III

What the outbox decides.

Sending mail is a few decisions about who may say what. outboxthing makes them once, before the provider is ever called.

  1. 1

    Who is sending

    A key per app, compared by its hash. An unknown key is a 401, and revoking one app's key touches no other app.

  2. 2

    As whom

    The key fixes the domain. A sender outside it is a 403, refused before anything leaves the box.

  3. 3

    Through what

    One provider credential that can only send, and a capture mode for everywhere that shouldn't.

App mail, both ways
Measure Per app outboxthing
Provider keys in apps one per app none
Domains a key can send as all of them one
Mail from development real, or a second account captured
Changing provider every app one host and password

More than one app sending mail?

Tell me what your apps send. outboxthing is how every project here will send its mail.

Get in touch