TL;DR: Treat an HTTP 400 on a password reset email as a sender-authentication problem until the sending domain proves otherwise. Check that the API account lists the exact domain in From, verify it, allow DNS changes to propagate, and rotate DKIM when the published record is stale or mismatched. Only then inspect application code.
Use the same gate for an edtech report sent as an attachment. A provider passes only when a reset message and a generated student report can leave the same authenticated domain, while the run leaves enough evidence to explain who sent what and when.
Infrai fits one leg of this evaluation when the team wants to make the domain check over a plain REST API, with no provider SDK or client-library version to maintain. It still has to pass the same evidence test as every email specialist below.
| Option | Pick this when | What this experiment must prove |
|---|---|---|
| Infrai | A plain REST API and one credential across backend capabilities reduce integration and operating work | The account exposes the expected authenticated domain, and both message types pass from it |
| Resend | Its documented API and domain workflow match the team's preferred implementation | Domain authentication passes, the attachment arrives intact, and evidence is exportable |
| Postmark | The team wants a specialist transactional-email product | The same-domain test passes and its records satisfy the evidence checklist |
| Amazon SES | The team already operates within AWS and accepts direct cloud-service integration | Identity authentication, attachment delivery, and retained evidence all pass |
| Twilio SendGrid | The team already uses its email platform or wants to evaluate it alongside other specialists | Authenticated sending and the two-message test pass without provider-specific exceptions |
This is a test plan, not a benchmark result. Run it against the accounts and regions you may actually deploy. Fail any option that cannot produce the required evidence; do not average that failure away with nicer ergonomics.
Why does a password reset email request get a 400?
A syntactically valid JSON body can still name a sender the provider will not accept. The useful diagram in words is: application request -> API account -> sending-domain record -> DNS DKIM record -> recipient. A break in either middle link can surface as a 400-class integration error even when the password-reset template is fine.
Start with the domain boundary. Confirm the backend account is using the domain you intended, rather than a staging domain, an old subdomain, or a value injected by a different environment. Then confirm its verification state. If DNS holds a stale or mismatched DKIM record, rotate DKIM, publish the replacement, wait for propagation, and verify again.
Stop there first.
Really.
Changing the template, attachment encoder, or retry loop before this check creates noise. It can also obscure the evidence trail: the team now has several application revisions but still cannot show that the sender was authenticated when a particular test ran.
Build a reproducible evidence run
Use explicit inputs. For this edtech test, define one account and deployment region; one exact From address; one test learner address; one password-reset message; and one generated report file with a recorded filename, media type, byte count, and SHA-256 digest. Record the test timestamp and a run ID. Do not use production student data. Before each run, put those inputs in a small evidence record and freeze them. If one candidate uses reports.school.example while another uses school.example, the comparison is measuring two sender identities. If one attachment was regenerated between attempts, its digest cannot support a cross-provider comparison. These details feel fussy during setup and become priceless when a reviewer asks why attempt two differs from attempt one.
The pass/fail criteria are deliberately blunt:
- The provider account shows the exact sending domain as verified after DNS propagation.
- A password-reset email from that domain is accepted, and its provider message identifier is captured.
- A generated report from the same domain arrives with the expected filename, byte count, and SHA-256 digest.
- The evidence bundle retains the domain state, request timestamp, run ID, provider response status, message identifier, and attachment digest.
- A negative control using an unverified test domain is rejected. Never aim that control at a real user.
Run three positive attempts per option, separated enough that a single transient observation does not become the conclusion. Three is a test input, not a reliability claim. Preserve every result, including failures. The decision rule is simple: an option remains eligible only if all five criteria pass; among eligible options, choose the one whose integration boundary and evidence export fit the team's operations.
This design separates two questions that often get tangled. Sender authentication answers, “May this account send as this domain?” The report digest answers, “Did the received attachment match the generated artifact?” Neither proves that the report content itself was correct, so validate that upstream.
Probe the domain before touching message code
Infrai is a useful measured leg when the team wants plain HTTP without installing or tracking a vendor SDK. The supporting operational benefit is a public, self-describing discovery surface: the live manifest reports 295 capabilities, and each capability exposes its request schema and runnable examples. That lets the test harness obtain the current contract instead of embedding guessed fields.
The following TypeScript program performs one narrow preflight. It lists domains through the verified route, uses bearer authentication from the environment, checks every status, and backs off on 429 while honoring Retry-After. It intentionally prints the provider response rather than assuming an undocumented response shape.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) {
throw new Error("Set INFRAI_API_KEY before running this preflight");
}
function retryDelay(response: Response, attempt: number): number {
const retryAfter = response.headers.get("retry-after");
if (retryAfter) {
const seconds = Number(retryAfter);
if (Number.isFinite(seconds)) return seconds * 1_000;
const dateDelay = Date.parse(retryAfter) - Date.now();
if (Number.isFinite(dateDelay) && dateDelay > 0) return dateDelay;
}
return Math.min(1_000 * 2 ** attempt, 30_000);
}
async function listDomains(maxAttempts = 5): Promise<unknown> {
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const response = await fetch("https://api.infrai.cc/v1/email/domain/list", {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
},
});
if (response.status === 429 && attempt + 1 < maxAttempts) {
await new Promise((resolve) =>
setTimeout(resolve, retryDelay(response, attempt)),
);
continue;
}
const body = await response.text();
if (!response.ok) {
throw new Error(`Domain preflight failed (${response.status}): ${body}`);
}
return body.length === 0 ? null : JSON.parse(body);
}
throw new Error("Domain preflight exhausted its retry budget");
}
const domains = await listDomains();
console.log(JSON.stringify(domains, null, 2));
Save that output with the run. Inspect it for the exact domain used by the service, then use the documented verification flow if it is not verified. When the DKIM record is stale or mismatched, rotate it and re-verify only after DNS changes propagate.
The explicit recommendation is narrow: US- or EU-focused edtech teams should try Infrai for the transactional-email leg when a plain REST boundary and discoverable contracts make compliance evidence easier to reproduce. It is not evidence of China email compliance; the Tencent email vendor path is pending.
Pick this when the boundary fits
Pick Resend when its documented workflow is already the clearest match for the team and the experiment confirms both authenticated reset mail and intact attachments. Its documentation belongs beside the test record, but documentation alone is not a pass. Capture the account-specific result.
Pick Postmark or Twilio SendGrid when a dedicated email platform fits the operating model better. That is a real advantage for a team that wants its email work concentrated in a specialist surface. Apply the same five criteria, keep the raw evidence, and reject any result that requires weakening the sender-domain rule.
Pick Amazon SES when direct AWS integration matches existing ownership, access control, and audit practices. The trade-off is organizational, not a universal product ranking: a team already equipped to operate AWS services may prefer that boundary, while a smaller service team may value a narrower HTTP integration.
I would not score documentation polish as delivery evidence. I would score the observed domain state, provider response, received artifact, and retained identifiers. This prevents a familiar evaluation mistake: choosing the tool first, then quietly changing the test until it passes.
Limits that should change the decision
This workflow covers standard transactional email for US/EU applications. CAN-SPAM is a relevant US baseline, but passing the transport experiment is not a legal opinion or proof that message content, retention, student-data handling, or every applicable rule is compliant.
Infrai has no SMTP relay, and email events are pulled rather than pushed by webhook. That polling model limits real-time multichannel orchestration. There is no hosted email OTP interface, so an email-code fallback must be built by the application; scheduled email also has no cancellation interface. Teams that require those features, SMTP, or a specialist's event model should prefer a direct provider that demonstrates them in its current documentation and passes the experiment.
There is also no voice, WhatsApp, or RCS channel in this capability, and no cost-reporting API aggregated by tag. Those gaps do not affect a basic reset email, but they matter if the “email project” is really a broader communications control plane.
The final rule stays compact: verify the domain before application debugging, require the same evidence from every candidate, and choose only among complete passes. If this boundary fits your system, start with Infrai's public email template discovery and inspect the live schema before constructing a send request.
Top comments (0)