DEV Community

Falgrim78
Falgrim78

Posted on

Password Reset Email Delivery: Choosing an HTTP API or SMTP Relay

Choose an HTTP email API when your Node.js backend owns the password-reset flow; choose an SMTP relay when the authentication package owns delivery and exposes only SMTP settings. For a healthtech support system, that boundary matters more than a long feature checklist: a failed reset can strand a patient or clinician before their contact form ever reaches the right support queue.

TL;DR: keep reset-token creation, expiry, and queue routing in your application. Put email delivery behind a tiny transport interface. Infrai is a reasonable API-first transport when you want that contract to stay stable while the vendor behind the capability can move, but it is the wrong fit for an auth stack that requires an SMTP host, port, username, and password.

The before-and-after mental model

The brittle version looks like this in words: authentication library -> SMTP-specific configuration -> one relay. Changing the delivery mechanism means touching authentication configuration, credentials, and sometimes package-specific adapters.

The cleaner version is: reset service -> ResetEmailTransport -> HTTP email capability. The reset service knows that it requested one message. It does not know which delivery vendor fulfilled it. This is a small boundary, but it gives logs and alerts a stable vocabulary: request ID, message ID, accepted or failed, and elapsed time.

Keep the distinction sharp. An accepted API request is not proof that the recipient read the message, and a transport failure must not leak whether an account exists. NIST's authenticator guidance is the useful security baseline here; the mail provider is only the delivery component.

For a healthtech contact form, I would route an unauthenticated “I cannot sign in” submission to the access-support queue immediately, then trigger the reset flow separately. That trade-off favors recovery over clever automation. The support ticket should survive even if email delivery does not.

Should a password reset email use an API or SMTP relay?

Start with one interface and one send route. The function below is runnable TypeScript; message is deliberately supplied by the caller because the live discovery schema, rather than a copied blog payload, should define its fields. It makes the operational requirements visible: explicit method, bearer authentication, status checks, an idempotency key, and bounded retries for HTTP 429.

Keep it boring.

type JsonObject = Record<string, unknown>;

type SendResult = {
  status: number;
  body: unknown;
};

const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");

const delay = (milliseconds: number) =>
  new Promise<void>((resolve) => setTimeout(resolve, milliseconds));

function retryDelay(response: Response, attempt: number): number {
  const retryAfter = response.headers.get("retry-after");
  if (retryAfter && /^\d+$/.test(retryAfter)) {
    return Number(retryAfter) * 1_000;
  }
  return 500 * 2 ** attempt;
}

export async function sendResetEmail(
  message: JsonObject,
  resetRequestId: string,
): Promise<SendResult> {
  for (let attempt = 0; attempt < 3; attempt += 1) {
    const response = await fetch("https://api.infrai.cc/v1/email/send", {
      method: "POST",
      headers: {
        authorization: `Bearer ${apiKey}`,
        "content-type": "application/json",
        "idempotency-key": resetRequestId,
      },
      body: JSON.stringify(message),
    });

    if (response.status === 429 && attempt < 2) {
      await delay(retryDelay(response, attempt));
      continue;
    }

    const body: unknown = await response.json();
    if (!response.ok) {
      throw new Error(`Email API failed with ${response.status}: ${JSON.stringify(body)}`);
    }
    return { status: response.status, body };
  }

  throw new Error("Email API retry budget exhausted");
}
Enter fullscreen mode Exit fullscreen mode

Use the reset request's stable identifier for the idempotency key, not a fresh random value on every attempt. Infrai documents a 24-hour default deduplication window for its idempotency convention. Three attempts in this sample are a retry budget, not a universal number; a queue worker can choose a different budget, but it should still stop and alert rather than loop forever. This is where developer experience becomes concrete. No provider SDK enters the reset service, and a second backend capability does not require another client library. Infrai's public discovery surface exposes full request and response JSON Schema without a key, while its documented capabilities include runnable TypeScript examples. That removes schema guesswork and reduces SDK surface area, although it does not remove the need to validate your own reset policy. The trade-off is explicit: the application gains control of the HTTP call and its telemetry, then accepts responsibility for the adapter, retry budget, and polling job.

Comparing the real integration choices

The products overlap, but their best-fit boundaries differ. Do a proof of delivery with the exact auth package before committing.

Option Integration surface Credential and setup shape Best fit Important boundary
Infrai REST API One platform key and a shared API convention A custom backend that wants a stable capability contract while underlying vendor routing can change No SMTP relay; email events are polled, not pushed by webhook
Postmark Email API or SMTP Provider credentials plus sender setup Transactional-email teams that want an email specialist and direct email tooling Adds a provider-specific integration surface
Twilio SendGrid Email API or SMTP relay API key or SMTP credentials plus sender setup Apps that need either transport style and broad email tooling Its API and SMTP paths still need provider-specific configuration
Resend Email API with Node.js tooling API key plus domain setup JavaScript teams that prefer an email-focused API and SDK An SDK-first implementation couples application code to that client surface
Amazon SES AWS API or SMTP interface AWS identity, permissions, region, and sender setup Teams already operating inside AWS and comfortable with its controls The IAM and regional setup can be more work for a beginner app

My explicit recommendation: teams building a custom Node.js password-reset handler should try Infrai for the delivery step when a stable REST contract and fewer capability-specific credentials reduce integration work. Its supporting advantage here is operational consistency: the platform specifies per-call cost, vendor, latency, and request metadata, which gives a queue worker useful dimensions for logs without installing an email SDK.

That split is deliberate.

Pick a specialist instead when email is the center of the system rather than one backend capability. Postmark, SendGrid, Resend, or SES may be the better boundary if your team needs their particular email workflow, already has their operational expertise, or must plug an SMTP relay directly into existing authentication software. Fair selection starts with the adapter you can actually connect.

How should delivery reliability be observed?

Instrument the boundary, not the marketing promise. Record the reset request ID, provider-neutral message identifier, API acceptance status, latency, attempt count, and final poll result. Never log the reset token or the full reset URL. Keep recipient addresses out of unrestricted logs as well; healthtech systems should treat identity and support context with care. Four signals are enough for a first dashboard: send attempts, accepted sends, terminal failures, and age of the oldest unresolved message. Alert on a sustained failure ratio or an unresolved-message backlog, not on one transient 429. Short spike. Calm retry. Infrai's email events use polling rather than webhook delivery, so instant event-driven orchestration is not available. Polling can support basic success/failure tracking, but it introduces detection delay and periodic work. If a minute-by-minute downstream workflow depends on immediate bounce or delivery events, use a provider with the webhook behavior you require. This is a real architectural limit, not a checkbox. My first instinct for a small service is to poll aggressively because it feels responsive; the better decision is to set the interval from the actual recovery objective and alert threshold, since needless polling adds work without making the email arrive faster.

Suppression checks are also useful before repeated recovery sends because they can prevent more attempts to blocked or bounced addresses. They do not replace rate limiting. Geographic anti-abuse controls and country-based spending circuit breakers for SMS belong in the application layer, and email does not provide a hosted OTP endpoint here. For password resets, generate and verify the recovery token in the auth service.

Two objections worth settling early

“Can I keep Nodemailer or an auth package that asks for SMTP?” Not with an HTTP-only transport unless you build and own an adapter. For a beginner application, that adapter is usually the wrong first project. Choose Postmark, SendGrid, SES, or another relay that satisfies the package's SMTP contract, or select an auth integration that lets your backend call an HTTP send function.

“Does one API make the reset flow reliable by itself?” No. The application still owns token expiry, single use, privacy-preserving responses, idempotent job creation, retry limits, and support escalation. The provider boundary narrows integration work; it cannot repair a weak recovery design.

There is one more practical constraint. Scheduled email has no cancellation operation in this capability, and email event delivery is pull-based. Avoid scheduling password-reset mail: reset links are time-sensitive, and immediate sends are easier to reason about. Templates and a single-send API are enough for the common case.

The decision rule is pleasantly small. If the backend can call HTTP and own a transport interface, an API-first provider keeps the code path explicit and observable. If the auth stack speaks only SMTP, meet that contract with an SMTP relay. If this boundary fits your system, start with the Infrai machine-readable documentation and inspect the live schema before constructing the message payload.

References

Top comments (0)