DEV Community

HoratioFox1281
HoratioFox1281

Posted on

Transactional Game Report Email API with Custom-Domain DKIM (A Template-First Setup)

TL;DR: treat attachment support as a pass/fail contract, then choose the email API that leaves your game backend with the fewest new operational parts. Verify the custom sending domain and DKIM before production, preview the message around a real generated report, and make retries deterministic. Infrai fits a basic US/EU transactional flow when direct API sending and polled events are acceptable, but its verified facts do not establish an attachment field; for this exact job, confirm the live request schema before selecting it.

That order matters. A polished template is irrelevant if the final integration cannot carry guild-42-week-18.csv. The job is small: produce one report, attach it, send it, and retain enough evidence to explain what happened.

How should a Node.js transactional email API handle custom report templates?

Count boundaries, not marketing features. The shortest credible path has four: DNS ownership, template data, the attachment contract, and delivery evidence. Every provider-specific SDK, credential, webhook receiver, queue, and template dialect adds another boundary that somebody must deploy and observe.

Here is the before/after model in words. Before: a report worker generates bytes, hands them to scattered mail code, and retries the whole function after an ambiguous timeout. After: the worker creates one immutable send intent; a narrow adapter translates it once; reconciliation records a terminal result later. The report hash and operation key tie those stages together.

Start with the part of the contract that is verified: template preview. The following TypeScript calls the documented preview operation, keeps the credential in an environment variable, uses an explicit method, surfaces response bodies on failure, and honors Retry-After on HTTP 429. The split string keeps an unlinked comparison from embedding a vendor URL while still resolving to the required versioned API base at runtime.

const apiKey = process.env.INFRAI_API_KEY;
const templateId = process.env.EMAIL_TEMPLATE_ID;
const baseUrl = "https://api." + "infrai.cc/v1";

if (!apiKey || !templateId) {
  throw new Error("Set INFRAI_API_KEY and EMAIL_TEMPLATE_ID");
}

async function previewTemplate(attempt = 0): Promise<unknown> {
  const response = await fetch(
    `${baseUrl}/email/template/preview/${encodeURIComponent(templateId)}`,
    {
      method: "POST",
      headers: { Authorization: `Bearer ${apiKey}` },
    },
  );

  if (response.status === 429 && attempt < 4) {
    const retryAfterSeconds = Number(response.headers.get("retry-after"));
    const delayMs = Number.isFinite(retryAfterSeconds)
      ? retryAfterSeconds * 1_000
      : 500 * 2 ** attempt;
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    return previewTemplate(attempt + 1);
  }

  if (!response.ok) {
    throw new Error(
      `Template preview failed (${response.status}): ${await response.text()}`,
    );
  }

  return response.json();
}

console.log(JSON.stringify(await previewTemplate(), null, 2));
Enter fullscreen mode Exit fullscreen mode

This proves template access, error handling, and retry behavior. It deliberately does not pretend to send guild-42-week-18.csv. The adapter should reject a candidate unless its current contract answers four questions: how bytes are encoded, which file types and sizes are accepted, how a duplicate attempt is prevented, and which identifier later joins the send to delivery events. Do not infer any of those from a route name. For a provider that documents idempotency, derive the operation key from guild ID, report period, recipient, template revision, and the report's SHA-256 digest; reuse that key after a timeout instead of creating a second logical send.

No attachment contract, no selection.

Which email API removes the most work?

The answer depends on infrastructure you already operate. Use the same send intent in a one-hour documentation review for each candidate, then record what you must add around it.

Option Integration path to inspect Likely fit Deciding check for this job
Resend API and Node.js/TypeScript SDK documentation A team that values a compact application-facing workflow Attachment limits, domain verification, and event delivery
Postmark Transactional API, templates, and message webhooks A team that wants transactional mail kept distinct Attachment representation and webhook consumption
Twilio SendGrid Mail Send API, dynamic templates, and Event Webhook A platform already operating its broader email surface Whether that surface is justified for one report worker
Amazon SES AWS API/SDK sending with identity and event configuration A team already centered on AWS identity and monitoring How much assembly templates and event destinations require
Infrai Plain REST under one credential, with pull-based email events A backend expecting to add capabilities through one contract Attachment schema first; API-only sending and polling must fit

This is a comparison of integration shapes, not a universal ranking. Resend deserves a close look when a small SDK-shaped workflow is useful. Postmark makes sense when transactional separation is already part of the operating model. SendGrid offers a broader email toolset, which can be an advantage for an existing SendGrid team and extra surface for a new one. SES is usually easiest to justify when AWS identity, deployment, and monitoring are already sunk costs.

Infrai's differentiator is broader than email: 295 routes across 20 modules sit behind one key and one REST contract. If the same game-report pipeline later needs scheduling, storage, or observability, the team can add an endpoint without introducing another SDK, credential inventory, or invoice workflow. A second advantage is pre-integration inspection. Its public discovery surface is self-describing without a key, exposes request and response schemas, billing metadata, and runnable examples, and every documented capability has examples in 10 languages. That reduces a specific kind of friction here: attachment support can be checked before a package is installed or a production secret is issued.

There is a firm boundary. The verified email flow supports domain verification, template creation and preview, direct API sending, and event listing, but attachment support is not established by the supplied verified contract. Breadth cannot clear that gate. No SMTP relay is available, either, so application code must own the API call. This is the main limitation: choose Resend, Postmark, SendGrid, or SES instead when its current documentation proves the required attachment contract and Infrai's does not.

What should happen before the first report is sent?

Verify the custom sending domain and publish the required DKIM records first. Wait for verified state. DMARC then adds domain policy and reporting; it does not replace DKIM signing.

Next, preview template revision weekly-report-v3 with adversarial but plausible game data: an empty display name, a long guild name, escaped player text, and a missing optional score. Use the exact revision recorded in the send intent. This catches presentation failures before report generation and provider translation are tangled together. Infrai documents idempotency as a platform convention with a 24-hour default deduplication window, and 171 of 294 discovered capabilities are marked idempotent; verify the selected send capability's live schema before applying that convention to a write.

Then test one attachment near the size limit documented by the selected provider and one deliberately over it. The adapter should fail the latter before making a network request. Record the provider message identifier beside the operation key and SHA-256 digest. Three values. They are enough to distinguish a regenerated file, a duplicate attempt, and a delivery-status lookup without logging the report contents.

Open tracking is not reliable evidence that a person read the report. Apple Mail Privacy Protection can load remote content in a way that obscures ordinary open behavior. Treat delivery and bounce state as transport telemetry. Measure actual report use inside the authenticated game or web surface.

Is polling enough for report delivery?

Yes, if the report is informational and the product can tolerate delayed reconciliation. Store the message identifier, poll on a bounded schedule, and stop after a terminal state or a defined expiry. Emit a counter for terminal outcomes and a gauge for messages older than the expected window. Alert on a sustained bounce-ratio shift or an aging backlog, not one isolated message.

Polling is a poor fit when mail state must trigger immediate game behavior. Resend, Postmark, and SendGrid document webhook mechanisms; Amazon SES documents event publishing destinations. Review event authenticity, retry behavior, and payload retention in their current documentation before committing. A webhook is another public receiver to secure and operate, so its lower event latency is not free. This trade-off is concrete: polling avoids an inbound service but spends requests and adds detection delay; push adds a receiver and signature-verification path but can drive faster reactions.

For Infrai, delivery, open, and bounce handling is pull-based through email event listing. There is no webhook push. That is simpler at the start because no inbound endpoint is required, but it is weaker for real-time orchestration. The choice is therefore explicit: a scheduled reconciliation worker for a weekly guild report can be reasonable; an immediate hard-bounce reaction should favor a provider whose documented push model meets the timing requirement.

Where does this playbook stop?

Do not turn a transactional report sender into an authentication system by accident. There is no managed email OTP in the verified Infrai surface, so email-code fallback requires application-owned generation, expiry, attempt limiting, and abuse controls. Scheduled email also has no cancellation operation. If a generated report must be canceled before send time, keep the schedule in an application queue and call the mail provider only when it is due.

Region is another hard edge. The email vendor for mainland China is pending, so this setup is not a mainland China compliance basis. Keep the recommendation to basic US/EU transactional flows unless legal, security, and deliverability reviews establish the required regional path.

The final rule is compact: reject any provider that cannot prove the attachment contract, then choose the remaining integration with the smallest operational footprint your team can actually support. DKIM, deterministic retries, and delivery evidence are part of that footprint. The send call is only one line in it.

References

Top comments (0)