The mail people are waiting for.
Delivered.
Iris carries the one-off messages your systems send on someone’s behalf: a sign-in code, a password reset, a receipt. It sends them exactly as written, keeps trying until the provider takes them, never sends one twice by accident, and runs on your own servers.
POST /t/acme/send
Authorization: Bearer iris_<id>.<secret>
Idempotency-Key: reset-7f3a
{ "to": "person@example.com",
"subject": "Reset your password",
"body": { "text": "Reset it here: https://..." } }
{ "message_id": "msg_001a13d6bb0f6...",
"status": "queued" }
Retry after a timeout with the same key and nothing new is admitted: you get the message the key first created. Your system can always try again.
Infrastructure, not a mail product
A mail server that stays a mail server.
Every mail service drifts the same way: templates, then hosted images, then open tracking, then click tracking, then reports. Each step looks reasonable, and together they turn the service that sends your password resets into a marketing tool. Iris draws the line on purpose, and keeps four promises.
It sends the bytes it was given
No tracking pixel, no rewritten links, no added footer. A reset link is a credential; Iris never routes it through anyone’s redirect.It holds no content
No templates and no hosted assets. Your system writes its own mail, versioned and reviewed with its own code. Bodies are dropped the moment a message is done.It has no audience
No lists, segments or campaigns. A message has its recipients and is sent once, so nothing in Iris can mail a thousand people by mistake.It reports delivery, not readers
Admitted, accepted by the provider, failed and why. Never who opened what.Built for the message that has to arrive
A late code is nearly as bad as a missing one.
Everything in Iris is shaped by that.
Retries that know when to stop
Throttling and outages are retried with backoff, honouring Retry-After. A refusal fails at once, with the provider’s reason. After eight attempts, Iris says so.
Tenants that share nothing
Each tenant has its own storage, keys, senders and delivery loop, so one stuck provider never holds up another tenant’s mail.
Two providers, each for its job
Microsoft 365 for mail from a real mailbox. Cloudflare Email Service for mail from a domain. Each sender uses the one its DNS points at.
Secrets kept out of reach
Provider credentials are stored wrapped and opened in memory only to send. The unseal key never has to live on the host.
Operators who prove who they are
The operator API answers only to a client certificate from your own CA, and logs every change with the certificate that made it.
Logs that name messages, not people
One JSON line per event, with recipients by domain only. Addresses, bodies and secrets are never written to a log.
How it fits
One binary. Your servers. Your keys.
Iris is a single Linux binary with its database built in. Your systems send to it over HTTP; your operators manage it over mutual TLS; it delivers through the provider each sender uses. Nothing about your mail depends on a service we run.
In service today
Already carrying real mail.
Iris delivers the sign-in codes, password resets and confirmations of Frogfish’s own products. It is working through a published release gate before general availability, and we will show you exactly where it stands.