One API and SMTP for every email Mentor, Sidekick and Hallelo send, from sign-in codes and receipts to launches and newsletters. Each project is kept apart from every other, and every email goes out under the product’s own name.
Your app calls the API or speaks SMTP. Herald checks the key, that the sender’s domain is verified and yours, the day’s quota and who’s suppressed, then answers in milliseconds. An idempotency key makes a retry safe: the same key, the same answer, one email.
import { Herald } from '@heraldmail/sdk'const herald = new Herald(process.env.HERALD_API_KEY)const { data, error } = await herald.emails.send( { from: 'Mentor <hello@mentor.app>', to: 'ada@example.com', subject: 'Your sign-in link', html: '<p>Sign in to Mentor: <a href="https://mentor.app/s/8Fq2">continue</a></p>', }, { idempotencyKey: 'sign-in/8Fq2' },)
02
Compose
Each recipient gets their own copy: a Message-ID, and a return path only Herald can read back, so a bounce or complaint finds its way to the right person in the right project. Proclamations carry one-click unsubscribe.
Two DKIM signatures: your domain’s, so your mail is aligned with DMARC, and Herald’s own, so complaint loops and Gmail’s Postmaster Tools can report back. The private keys never leave Herald’s keyring.
KumoMTA delivers it at each provider’s pace, from the project’s own pool of addresses. It always tries TLS, and enforces MTA-STS and DANE where a domain asks for them.
SMTP, to the recipient’s server
S: 220 mx.google.com ESMTPC: EHLO mta-1.heraldmail.emailS: 250-STARTTLSC: STARTTLS … TLS 1.3, certificate checked against MTA-STS …C: MAIL FROM:<b-5hssj.k3mxq7v2rd.2c4a9f@send.mentor.app>C: RCPT TO:<ada@example.com>C: DATAS: 250 2.0.0 OK 1793648712 x7si2215204wmb.142 - gsmtp
05
Report
Deliveries, bounces and complaints come back and are matched by the token in the return path, never by an address someone could forge. Your webhook hears about each one, signed, and retried for three days if it doesn’t answer.
Mentor can’t read Sidekick’s mail, reach its contacts, or send from its domain, even by mistake. Isolation isn’t a filter in the code: the database, the keys and the mail servers all enforce it.
Row-level security on every table
Postgres answers only for the project in the request’s context, live or test.
A key for each project
Its mail and secrets are sealed under its own data key, which only the keyring can open.
Its own queues
The mail servers queue and pause each project apart: stopping one stops nobody else.
Tokens that can’t be reused
Every link and return path is signed for its project; another project’s token resolves nothing.
Add a domain and Herald gives you its records: DKIM for your signature, a return path for bounces (your own SPF is left alone), and DMARC. Each one turns green as it’s found, and Herald keeps checking: Console shows you if one goes missing.
A bought list or an unwanted newsletter can ruin a domain’s reputation in an afternoon. Herald watches every broadcast at every mailbox provider, starts with a canary, and stops before Gmail’s and Yahoo’s lines, not after.
Broadcasts to 200 people or more send a 5% canary first; the rest waits for it.
Imports prove themselves: a sample goes first, and a list that bounces is held.
A Proclamation to 5,000 people at one provider. Move the sliders.