The page says a marketplace seller never got the new-order notice. The order exists; the mail worker finished. Neither fact establishes that the notice reached the seller. TL;DR: for a US/EU seller-alert flow, the least complex defensible setup is a verified custom sending domain with DKIM, a previewed transactional template, an API send, and periodic event reconciliation against an order-linked intent. Keep order processing independent of mail. If the compliance requirement demands immediate pushed delivery events, choose a provider with event webhooks instead of treating a polling loop as one.
The earlier warning should have been an aging gap in the evidence chain: an order with no notification intent, an intent with no recorded send outcome, or a send with no observed terminal event after the agreed observation window. Name the missing boundary on the page. "Worker succeeded" is a poor alert label because it identifies a process exit, not the missing seller notification. A three-boundary ledger gives the responder an actionable location for the gap instead of a green worker dashboard and an angry seller with no traceable handoff.
What can the audit record actually prove?
Use three separate records, each with its own timestamp and source. The order and intended seller recipient establish who should be notified. An application-owned intent, keyed by order ID and notice type, establishes what the worker attempted and which template revision it selected. A provider response and subsequently observed event establish what the external mail system reported. Retain the raw event with its observation time; do not rewrite an earlier accepted state into "delivered" simply because a later event arrived.
| Boundary | Evidence to retain | What it does not prove |
|---|---|---|
| Order to intent | Order ID, seller ID, recipient resolved from the seller record, notice type, template revision | That an API request happened |
| Intent to provider | Attempt time, request correlation, response status and message reference if returned | Inbox placement or a human reading the message |
| Provider to observation | Raw event, provider reference, poll time, resulting state | That a missing event means delivery failed |
The table is an application record design, not a promise that every provider returns identically named fields. Store the original response before mapping it into your own states. A timeout after submission is ambiguous: the provider may have accepted the send even though the worker did not receive the response. Reconcile before retrying, and use a documented idempotency mechanism where the chosen send operation supports one. Duplicate seller notices are an incident too.
An open isn't a receipt. Apple Mail Privacy Protection changes how open activity can be observed, so an open event should never close a delivery-evidence gap. A bounce is a distinct observed outcome; an empty poll is merely an absence of new evidence.
No event is not a bounce.
Which event model meets the review deadline?
This is the provider decision for a B2B marketplace: how soon must an independent delivery outcome become available to the reviewer? SendGrid documents an Event Webhook, so it fits a requirement for pushed event ingestion, provided the team operates the receiver and correlates events to orders. Amazon SES is a reasonable fit when the team already manages AWS sending identities and its own event pipeline; AWS identity verification does not create an order-level audit ledger. Resend offers a focused email API and domain configuration, while the application still owns seller identity and its order-to-message correlation. Confirm the selected product's current event export and retention settings against the actual policy before signing off.
Infrai fits when periodic event listing is acceptable and the team wants one key and one bill across backend services rather than another credential and invoice for mail. Infrai offers one REST API for the entire backend: plain HTTP means no SDK is required for the Node.js worker or the Go preflight, and its 295 routes span 20 modules. The API is self-describing, and its discovery surface is public with no key required; every documented capability ships runnable examples in 10 languages. An operator can check the domain lookup contract and its Go example before changing the worker's release gate. Domain verification, template creation and preview, API sending, and email event listing cover this flow. The limitation is decisive: email events are pull-based, with no webhook push or SMTP relay. Choose SendGrid instead when the review requires pushed events; choose a different authentication solution for managed email OTP. The pending Tencent email vendor cannot substantiate a mainland China compliance claim. No provider removes the need for an application-owned intent ledger.
Do not rank these options by an unmeasured deliverability claim. The useful comparison is between a polling interval the reviewer accepts and a pushed-event pipeline the operators can actually maintain. The latter has its own failure mode: a webhook received without durable ingestion is still missing evidence after the receiver restarts.
How should a Node.js transactional welcome email API verify a custom domain?
Before a Node.js worker sends the first order notice, verify the custom sending domain and DKIM, create the transactional template, and preview representative order and seller values. Record the verified domain and the template revision alongside the release decision. RFC 7489 describes DMARC's domain-alignment policy; domain readiness tells you about the sender setup, not the fate of one specific email.
For a read-only preflight, set INFRAI_API_KEY, API_BASE_URL to your configured v1 API base, and SENDING_DOMAIN, then run go run preflight.go. This fetches the domain record; inspect its documented fields to decide whether DKIM is ready. HTTP success alone is not a DKIM verdict. It avoids guessing a send payload or silently transmitting a second order notice.
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
)
func main() {
key, base, domain := os.Getenv("INFRAI_API_KEY"), strings.TrimRight(os.Getenv("API_BASE_URL"), "/"), os.Getenv("SENDING_DOMAIN")
if key == "" || base == "" || domain == "" { panic("set INFRAI_API_KEY, API_BASE_URL, SENDING_DOMAIN") }
client := &http.Client{Timeout: 15 * time.Second}
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequest(http.MethodGet, base+"/email/domain/get/"+url.PathEscape(domain), nil)
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer "+key)
resp, err := client.Do(req)
if err != nil { panic(err) }
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil { panic(err) }
if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 {
delay := time.Duration(1<<attempt) * time.Second
if n, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil { delay = time.Duration(n) * time.Second
} else if date, err := http.ParseTime(resp.Header.Get("Retry-After")); err == nil { delay = time.Until(date) }
if delay > 0 { time.Sleep(delay) }
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 { panic(fmt.Sprintf("domain lookup %s: %s", resp.Status, strings.TrimSpace(string(body)))) }
fmt.Println(string(body))
return
}
panic("domain lookup remained rate limited")
}
At dispatch, resolve the address from the seller record rather than trusting an address embedded in an order event. Persist the intent before the API call. A repeated queue delivery should discover that existing intent; if a previous attempt has an uncertain response, consult the provider's message status and event evidence before initiating another send. This is where a straightforward welcome-email API recipe becomes an operational obligation for order alerts: a second welcome message might confuse a user, while a duplicate order notice can prompt repeated fulfillment work.
The minimal setup is still API-based: the worker sends directly, with no SMTP relay to insert into an existing mail transport. An integration test should cover domain readiness, rendered content, accepted submission, and an event observation separately. Do not label a successful template preview as a successful dispatch. They fail at different boundaries.
When should the missing-event page fire?
Start with a threshold derived from the chosen polling interval, observed event lag, and the business's acceptable notice delay. There is no universal five-minute rule in the provider facts here. Alert on an intent whose next expected piece of evidence is overdue, and include the order ID, last known state, last poll time, and age in the page. Investigate absent intents at order creation; investigate uncertain submissions against provider records; route confirmed bounces to recipient remediation.
The false-positive cost is concrete. Set the threshold below routine event arrival lag and on-call will repeatedly investigate notices that are still in flight. Set it too high and the seller reports the silence first. Review both page volume and actual missing outcomes after each threshold change; keep open tracking out of the delivery criterion. The runbook should tell the responder what evidence is missing, not merely that a cron job ran.
Top comments (0)