Messaging
Resend email for GoCommerce
A Go package that sends a GoCommerce store’s emails — order confirmations, shipping notices, password resets — through Resend. An API key is the only required setting; until a domain is verified, mail goes from Resend’s onboarding address.
- Messaging module
- 8 settings
- 5 tests
- ext/notify-resend
What it does
The module registers a notifier on the engine’s email channel. When the engine has something to tell a shopper — an order placed, paid, shipped, delivered, cancelled, refunded or returned — it hands the module the event and flat data such as order_number, items_summary and tracking, and the module sends one plain-text email through Resend’s POST /emails.
The package calls it the email provider a store should reach for first, and shapes it so that is one field. Resend lets any account send from onboarding@resend.dev without verifying a domain, so a store with nothing but a key sends from there — which, in the package’s words, is what makes the first order confirmation arrive on the day the store is set up rather than the week the DNS is finished.
The wording is not the module’s. It asks the engine’s notification templates for the subject and body at send time, so what an operator edits under Notifications › Setup Email is what goes out. And whatever happens — sent, rejected, or never attempted for want of a key — the message is written to the log.
Configuration
Only the API key is required; everything else has a default that still sends. Set it in Config from your own main(), or leave Config empty and type it under Notifications › Setup Email.
| Setting | Environment variable | Required | What it does |
|---|---|---|---|
APIKeyAPI key | RESEND_API_KEY | Yes | A Resend API key. The one setting with no default, because it belongs to the store rather than the engine. |
FromFrom address | RESEND_FROM | No | A sender on a domain Resend has verified; onboarding@resend.dev when empty. Watch this one: the panel field defaults to that address and is read before Config, so a From set only in Config or RESEND_FROM is ignored until it is typed into the panel too. |
FromNameFrom name | RESEND_FROM_NAME | No | The name beside the address in the inbox. |
ReplyToReply-to address | — | No | Where a shopper’s reply lands; empty means the from address. |
Subjects | — | No | Overrides the engine’s subject for an event, keyed by event name, for a store that keeps its wording in code. Checked when the store boots; a subject edited in the panel wins. Go only. |
Bodies | — | No | The same, for the plain-text body. Go only. |
BaseURL | — | No | Overrides https://api.resend.com, for tests. Go only. |
Client | — | No | Replaces the HTTP client, which otherwise times out after 15 seconds. Go only. |
The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own main() you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.
Setting it up
- Create an API keyIn Resend. Verifying a sending domain can wait: until it is done, mail goes from onboarding@resend.dev, Resend’s address for accounts without one.
- Install the moduleImport it and pass resend.New to gocommerce.New, as below — or run the reference binary with -resend, which reads RESEND_API_KEY, RESEND_FROM and RESEND_FROM_NAME.
- Switch it onA key in Config starts it switched on. Otherwise switch it on under Notifications › Setup Email and paste the key there; it counts on the next message, with no restart.
- Edit the wordingSubjects and bodies are the engine’s templates, edited under Notifications › Setup Email. Place an order and the confirmation goes out.
main.go
import (
"os"
"github.com/itswadesh/gocommerce/core"
resend "github.com/itswadesh/gocommerce/ext/notify-resend"
)
app, err := gocommerce.New(cfg,
resend.New(resend.Config{APIKey: os.Getenv("RESEND_API_KEY")}),
) The package doc’s own example, with its imports; cfg is your gocommerce.Config. With an empty resend.Config the module installs idle and waits for the panel. Import path github.com/itswadesh/gocommerce/ext/notify-resend.
How it works
-
The engine’s words
Subject and body come from the engine’s templates at send time — the panel’s edit if there is one, Config’s Subjects and Bodies if not, the engine’s default otherwise — rendered with Go’s text/template over the event’s flat data.
-
Every message written down
Sent, with the id Resend filed it under; rejected, with Resend’s reason; or not attempted because there is no key. A store cannot look healthy for months while nobody receives anything.
-
Rejections settle, outages retry
A 4xx other than 429 is logged and settled: a bad address will be rejected again. Unreachable, 429 or 5xx is returned as an error, and the engine retries the notification with backoff.
-
Overrides checked at boot
A Subjects or Bodies template that does not parse stops the store booting, rather than failing on the first sale.
-
Only events with wording
An event with no email template is skipped, not an error, so another module can add events this one has never heard of.
-
Settings without a restart
The panel’s values are read on every send. The engine keeps a row per message in its notification log, and an operator can resend one from there.
What it does not do
Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.
- Config’s From is shadowedThe panel’s From field defaults to onboarding@resend.dev and is read before Config, so a sender set only in code or RESEND_FROM is not used — type it into the panel. For the same reason the sent line’s default_sender flag reads false even when mail goes from the onboarding address.
- Plain text onlyEach email is sent as text. There is no HTML body and no attachment.
- Amounts in minor unitsThe engine hands templates totals in minor units — 49900, not 499.00 — and a store that wants them formatted edits the template.
- Two backends, two emailsEvery configured email backend gets every message. With Resend and SendGrid both switched on, a shopper gets two; and a retry after one fails re-sends through both.
- Refusals count as sentA message Resend refuses returns no error, so the engine’s notification log records it as sent. The refusal is only in the application log.
- No bounce trackingThe module registers no webhook. Bounces, complaints and opens stay in Resend.
FAQ
Questions about the Resend module
Do I need a verified domain first?
No. With only an API key, mail goes from onboarding@resend.dev, which Resend lets any account use. Verify a domain when there is one and type the new address into the From field in the panel.
Where do I change what the emails say?
Under Notifications › Setup Email, where the engine’s templates are edited. A store that keeps its wording in code can pass Subjects and Bodies in Config instead; an edit in the panel wins over both.
Why Resend rather than SendGrid?
The reference binary’s own comment puts Resend first because it works with one setting: a key and nothing else sends. SendGrid needs a verified sender before anything goes out. Both modules send the same engine templates.
Is this a Resend partnership?
No. The module calls Resend’s public API with a key you supply. Resend does not endorse GoCommerce, and no store is known to run this module in production yet.
Source
Everything on this page is read from ext/notify-resend in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.Resend is a trademark of its owner; this module talks to its public API and implies no endorsement. See trademarks.
Try it against a store of your own
The one-command stack gives you GoCommerce’s API and admin on your own machine in minutes. Add this module to it and try it on test orders before a real one depends on it.