This is what we do with ourselves. The Kourio dashboard authenticates with Better Auth, and
its reset and verification emails leave through our own transport. This guide is our production
code with the names changed.
Install
.env
The minimum that works
auth.ts
One sender, in one place
After the third hook, the same block starts getting copied with a different comma. Worth extracting before that:mailer.ts
Magic link
One-time code (OTP)
Organization invitation
With a Kourio template
If you want your brand in the email without writing 2007-era HTML, publish a template in the dashboard and send only the variables. Subject and sender come from it:Each template block is a contract: given that content, Kourio guarantees it renders correctly
in Outlook, in dark mode, and at 600px wide. You write the text; the markup is our problem.
Three things that only show up in production
Send text alongside html — always
Send text alongside html — always
HTML-only mail scores worse with spam filters, and a password reset is exactly the one that
cannot land in the wrong folder. The
text field costs one line.Do not let a send failure take down the response
Do not let a send failure take down the response
If
sendResetPassword throws, Better Auth propagates the error to whoever asked — and the
difference between “sent” and “error” tells an attacker which addresses exist in your
database. Log the failure and answer the same either way.Authentication is not marketing
Authentication is not marketing
Leave these sends as
TRANSACTIONAL, which is the default. The class decides which
reputation the message leaves under, and the two are measured apart precisely so a bad
campaign cannot stop someone from getting into their own account.When it does not arrive
1
Check that the domain is verified
No message leaves a domain without SPF, DKIM and DMARC published. See Domains.
2
Look the message up by address
GET /v1/emails?search=… brings the timeline: accepted, delivered, deferred, bounced. It is
what answers “did it arrive?” without depending on your logs.3
Check whether the address is suppressed
An address that hard-bounced stops receiving — transactional included. See
Errors.
Sending
The two ways to compose a message, what counts against your quota, and why marketing takes a
different path.