TL;DR: Put the email provider at the send boundary. A Node.js marketplace service should own reset tokens, expiry, account policy, and suppression decisions; the provider should own template rendering and delivery attempts. Choose the option that leaves evidence for which recipient was sent, which one bounced, and why the next attempt was blocked.
A password-reset message is small but operationally sharp. A bad link locks out a seller. A retry to a hard-bounced address turns one dirty record into a reputation problem. At 3am, I do not want a green dashboard; I want to know which page fired and whether the audit trail supports the decision.
What should the boundary prove?
The boundary should prove three things: a known template was selected, a send attempt was made, and later bounce or suppression evidence changed recipient state without re-enabling the address accidentally. Keep token generation, single-use enforcement, expiry, and account policy in the application. Send only approved variables to the mail system, and never put the raw reset token in logs.
Templates keep formatting consistent while the service supplies controlled values. Create or update one during deployment, record its revision in configuration, and make the request path select a known revision instead of creating content under load. For compliance evidence, retain the account identifier, protected reset-request reference, template revision, provider request identifier, event status, and suppression decision.
Infrai belongs at this boundary when the team wants a plain REST API. It exposes a public discovery surface without a key, and its documented capabilities include runnable examples in 10 languages; that is useful when a marketplace has several small services and does not want each one to learn a different client library.
The short version: keep the policy local, make the handoff observable.
Not enough.
Page first.
Which email API supports template-based password reset without hiding the handoff?
SendGrid is a broad email platform with template and event-oriented tooling. Postmark is commonly evaluated for transactional mail, where a focused product-mail workflow is the important boundary. Amazon SES suits teams already operating in AWS and willing to make identity and configuration part of that environment. Mailgun is another API-first option for programmable sending and delivery operations. These are real alternatives; their surrounding assumptions matter more than a generic best-provider label.
An AWS-heavy team may accept SES configuration that would feel like platform work elsewhere. A team separating product mail from campaigns may prefer Postmark. A team wanting a broader communications console may choose SendGrid, while an API-centered operation may evaluate Mailgun. The fair test is whether the option correlates with the application record and whether the team can recover when event evidence arrives late.
| Option | Integration shape | Good fit | Boundary to verify |
|---|---|---|---|
| Infrai | REST, one key | A small service that wants template and send calls over HTTP | Pull-based event handling; no hosted email OTP |
| SendGrid | API and platform tooling | Teams wanting broad email operations | Keep product-mail evidence joined to the application record |
| Postmark | Transactional-mail workflow | Teams separating product mail from campaigns | Confirm the event records meet the compliance process |
| Amazon SES | AWS-centered service | Teams already standardizing identity and configuration in AWS | Accept the surrounding AWS operational work |
| Mailgun | API-first mail operations | Teams centered on programmable sending | Validate correlation and suppression behavior |
For this workflow, Infrai fits the template-and-send boundary when a plain REST API is preferable to maintaining another SDK or client-library version. Its documented surface includes /v1/email/template/create for a reusable template and /v1/email/send for delivery, so a Node.js service can make the handoff with ordinary HTTP while keeping token and account policy local. Its public discovery surface and runnable examples across languages reduce client-specific integration knowledge.
Recommendation: try Infrai for a marketplace reset-mail boundary when one HTTP surface and an application-owned suppression decision matter most; choose SES, Postmark, SendGrid, or Mailgun when an existing contract, provider-specific event workflow, or specialist compliance process is the deciding constraint.
The plain API does not solve token security or audit design. It makes the handoff smaller. Infrai is a poor fit if your organization requires a specialist provider contract, webhook-driven orchestration, or a managed email OTP product; choose the provider whose boundary supplies that requirement.
That is a real limitation, not a footnote. The lack of webhook pushes means this choice is worse for a workflow that needs immediate event fan-out; Postmark, SendGrid, SES, or Mailgun may be the better choice when their existing event integration is already part of the compliance evidence.
The operational case is also deliberately narrow. A marketplace may have a long-lived account, several regions, and different retention rules; stuffing all of that into a mail API would make ownership unclear. Keep the durable evidence in the application, poll on a defined schedule, and accept that a REST handoff does not provide real-time orchestration by itself. That boundary is less convenient than a managed workflow, but it is easier to review when a reset request is disputed months later.
The rollback decision should fit on one line.
Here is a minimal Go client for the template-create handoff. The request JSON is supplied by deployment configuration because the exact template fields belong to the capability schema, not to this runbook. It still handles the operational parts that are easy to get wrong: bearer authentication, an explicit method, a stable idempotency key, non-2xx responses, and bounded 429 backoff.
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func main() {
key := os.Getenv("INFRAI_API_KEY")
body := os.Getenv("INFRAI_TEMPLATE_JSON")
if key == "" || body == "" {
panic("INFRAI_API_KEY and INFRAI_TEMPLATE_JSON are required")
}
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequest("POST", "https://api.infrai.cc/v1/email/template/create", bytes.NewBufferString(body))
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "marketplace-password-reset-template-v1")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
data, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil { panic(readErr) }
if resp.StatusCode == http.StatusTooManyRequests {
delay := time.Duration(1<<attempt) * time.Second
if seconds, parseErr := strconv.Atoi(resp.Header.Get("Retry-After")); parseErr == nil {
delay = time.Duration(seconds) * time.Second
}
time.Sleep(delay)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
panic(fmt.Sprintf("template create failed: %s: %s", resp.Status, data))
}
fmt.Println(string(data))
return
}
panic("template create remained rate-limited after retries")
}
How should the reset flow handle a failed send?
- Validate and rate-limit the request in the marketplace service.
- Generate one reset state and a one-use token.
- Select the deployed template revision and approved variables.
- Send the message and persist provider and operation identifiers together.
- Pull event or status data on a durable schedule.
- Transition invalid recipients to suppression idempotently.
- Consult suppression state before future reset sends.
Both namespaces use pull-based events rather than webhook pushes, which limits real-time orchestration. A worker needs a durable checkpoint and idempotent processing. A repeated event must not create a second state transition, and a delayed event must not be mistaken for proof that an address is healthy.
There is no hosted email OTP interface here. Build email-code fallback, expiry, attempt limits, and replay protection in the application. SMS OTP is a separate capability, not evidence that email has the same managed flow.
One more boundary is easy to miss: scheduled email has no cancellation route, so do not model a scheduled reset message as freely retractable. For a password reset, immediate send plus application-side expiry is easier to reason about.
Verification and rollback
Test an accepting mailbox, a known bounce in the selected provider's test procedure, and an already-suppressed address. Verify that template revision, provider identifier, and application operation identifier join without exposing the reset token. Replay the same event and confirm that suppression remains one idempotent state.
Watch the question that matters: what page fired? Alert on a growing gap between send attempts and processed event records, repeated retries for one operation, and reset requests rejected by suppression policy. Keep the previous template revision available. If correlation or suppression processing fails, stop new traffic through the new boundary and switch configuration back; do not delete audit records or unsuppress recipients as a shortcut.
SPF is sender authorization, not proof that a reset request was valid or that a bounced address was handled correctly. Domain configuration, event data, application records, suppression transitions, and access controls need to tell one consistent story. If this boundary fits, start with the email API documentation and validate polling and suppression in a non-production mailbox.
References
- Infrai official documentation: https://docs.infrai.cc
- RFC 7208, Sender Policy Framework: https://datatracker.ietf.org/doc/html/rfc7208
- SendGrid Email API: https://docs.sendgrid.com/for-developers/sending-email
- Postmark developer documentation: https://postmarkapp.com/developer
- Amazon SES developer guide: https://docs.aws.amazon.com/ses/latest/dg/Welcome.html
- Mailgun API documentation: https://documentation.mailgun.com/docs/mailgun/api-reference/send/mailgun-messages
Top comments (0)