hermes

Implement transactional email

Implements transactional email with templates, a provider integration, retries, bounce and complaint handling, and deliverability settings. Use when an app must send receipts, resets or alerts.

context

Transactional email fails silently: a reset link that lands in spam, a receipt sent twice because a request retried, an email sent for an order whose transaction then rolled back, a provider outage that drops messages, or a bounced address the app keeps mailing until the provider suspends the account. Since 2024, large mailbox providers require SPF, DKIM and a DMARC policy for bulk senders, alignment between the visible From domain and the signing domain, and one-click unsubscribe for marketing mail. Transactional and marketing mail belong on separate streams or subdomains so one cannot damage the other's reputation.

task

Implement transactional email for:

stack

Only if [EMAILS_NEEDED] is given: Emails needed:

emails needed

  1. If the stack is unclear, ask once and stop. Read existing mail, job and config code if you can.
  2. Design. Send from a background job, never inside the web request. Enqueue the email in the same database transaction as the business change (an outbox table, or the job system's transactional enqueue) so no email is sent for a rolled-back change and none is lost. Give each message an idempotency key derived from the event (for example order-receipt:<order_id>) and skip duplicates. Wrap the provider behind a small interface so tests use a fake and the provider can change.
  3. Templates. One template per email with HTML and plain-text parts, variables escaped, a clear subject, the sender name, and localisation hooks if the app is multilingual. Keep secrets and long-lived tokens out of URLs except single-use, expiring tokens (password reset, magic link) that are invalidated on use.
  4. Sending and retries. Use the provider's official SDK or HTTP API. Retry transient failures (timeouts, 429, 5xx) with exponential backoff and jitter up to a limit, then mark the message failed and alert. Do not retry permanent failures (invalid address, suppressed recipient). Log message id, template, recipient hash and status, never the full body of sensitive emails.
  5. Bounces and complaints. Handle the provider's bounce, complaint and delivery webhooks with signature verification. Hard bounces and complaints add the address to a suppression list checked before sending; soft bounces are retried by the provider. Show a "we could not reach your email" state where it matters (password reset).
  6. Deliverability setup. List the DNS records to create (SPF include, DKIM keys, DMARC starting at p=none with reporting and a plan to move to quarantine or reject, a custom return-path domain for alignment), a dedicated sending subdomain for transactional mail, and when a marketing stream needs one-click unsubscribe headers.
  7. Tests. Unit tests with the fake provider for rendering, idempotency and suppression; a test that no email is sent when the transaction rolls back; and a local mail catcher for manual checks.
constraints
  • Use the provider's documented API; if unsure of a method, header or webhook field for the version in use, say so rather than guessing.
  • Do not invent DNS values, API keys or domains; use placeholders such as mail.example.com.
  • Never send marketing content through the transactional stream.
  • Do only what was asked. If you notice something else worth changing, mention it in one line at the end instead of changing it.
  • Keep the change as small as it can be while still being correct.
  • Before saying the work is done, run the check that proves it (tests, build, type check or the command the user gave) and report the real result.
  • If you could not run a check, say so plainly and say which one.
output format

Design

Bullets plus a short sequence of the send flow.

Templates

One template in full as an example, then a table of the others with subject and variables.

Code

Code blocks with file paths: interface, provider adapter, job, outbox or enqueue.

Bounces and complaints

Webhook handler code and suppression logic.

Deliverability setup

A table of DNS records with placeholder values and purpose.

Tests

Code blocks with file paths, then the real result of running them, or a plain statement that they were not run.

Open questions

Numbered, or "None".

1 required value still a placeholder; the assistant will ask for it.

details

kind
Prompt: a task you run by name to get one finished thing back
domain
Software engineering
category
Implementation
level
Intermediate
made for
Backend engineer, Full-stack engineer, Software engineer, Founder / business owner
needs
repo-read, file-write
risk
edits-files
version
v1.0.0 · incubating
reviewed
2026-10-03
works in
Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md

Edit on GitHubReport a problem

use in

Hodios CLI
npx @hermes-hq/hodios install implement-transactional-email --target claude-code
Agent Skills
npx skills add hermes-hq/hodios-dist --skill implement-transactional-email -a claude-code
Add the Hodios marketplace (once)
claude plugin marketplace add hermes-hq/hodios-dist
Install the software-engineering plugin
claude plugin install hodios-software-engineering@hodios

The plugin brings every entry in this domain at once.

pairs well with

All of Implementation
PersonaImplementation

Backend engineer

Acts as a backend engineer focused on correct data handling, clear API contracts, explicit failure modes and services that are easy to operate. Use as a builder or reviewer persona for server code.

backend-engineer
PromptImplementation

Implement a background job

Implements a background or scheduled job with idempotency, retries with backoff, dead-letter handling, timeouts, concurrency limits and observability. Use to move slow work off the request path.

implement-background-job
PromptImplementation

Build a webhook handler

Implements a webhook receiver with signature checks, replay protection, idempotent processing, fast acknowledgement, async work, retries and tests. Use when integrating Stripe, GitHub or similar.

build-webhook-handler
PromptSecurity

Plan secrets management

Plans secrets management for a stack, covering inventory, storage, runtime injection, rotation, access control and leak detection. Use when secrets live in env files, CI variables and chat.

plan-secrets-management
PromptImplementation

Put a change behind a feature flag

Wraps new behaviour behind a feature flag with a safe default, a kill switch, tests for both paths and a cleanup ticket. Use when shipping a risky change incrementally.

add-feature-flag
PromptImplementation

Add rate limiting to an API

Adds rate limiting to API endpoints with a fitting algorithm, keys, per-tier limits, standard headers, 429 responses and tests. Use when protecting endpoints from abuse or overload.

add-rate-limiting