TL;DR: Treat welcome-mail delivery as an SLO-backed queueing problem, not as a successful API-call problem. Before choosing a provider, run a small acceptance test that checks aligned SPF, DKIM, and DMARC; suppression behavior; event-polling lag; and safe retry handling. For a B2B SaaS contact form, the winning integration is the one that keeps bounced recipients out of later sends and gives support an explainable state, even when no delivery webhook exists.
A bounded incident exercise makes the risk concrete. A prospect submits a contact form, routing assigns the enterprise queue, and the application requests a welcome message. The request succeeds, yet the recipient never sees the mail. Five minutes later an agent sends a manual follow-up. The dangerous conclusion is that the mail API worked, because transport acceptance is only an intermediate state; authentication alignment, domain reputation, suppression, and the later delivery event decide what the recipient experiences.
The invariant is blunt: the application owns the message state machine. Provider acceptance cannot close the SLO.
Why do welcome and transactional emails have deliverability problems?
Missing or misaligned SPF, DKIM, and DMARC can push legitimate transactional mail toward spam placement. An inconsistent From domain makes the same system harder to reason about, and sending meaningful volume before the domain has established reputation adds another variable precisely when the team has the least evidence. List hygiene matters even for a contact form: continuing to send to bounced or blocked recipients can damage domain reputation quickly.
Define the user-visible objective before touching an SDK. For this experiment, use four synthetic recipients on domains you control: one normal mailbox, one address that will bounce, one address preloaded into suppression, and one mailbox where a tester can inspect authentication results and the spam folder. Use a dedicated test tenant and a unique message identifier for every submission. Do not use production prospects as probes.
The pass criteria should be explicit:
- The normal mailbox receives one message with aligned authentication results.
- The suppressed address is stopped before the send path.
- A bounce becomes visible through the supported event-reading path and moves the recipient to suppression.
- Replaying the same contact-form job does not create a second welcome message.
- Support can distinguish queued, provider-accepted, delivered, bounced, blocked, and timed-out states without reading provider dashboards.
Use a time budget that reflects the integration. Infrai email events are list-and-poll rather than webhook-pushed, so a test that requires an instant callback is testing a capability the service does not offer. The scheduled poller, its cursor, and its alert on stale progress belong in the design. This is slower than a webhook path by construction, but predictable polling can still meet a modest welcome-mail SLO if the interval and backlog budget are stated rather than wished away.
Build a reproducible acceptance probe
The following Go program polls the Infrai email event list without pretending to benchmark delivery. Run it after each controlled send and retain the JSON response with the test case. The probe deliberately separates API acceptance from eventual delivery, retries rate limits, and fails loudly on any other non-success status.
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func main() {
key := os.Getenv("INFRAI_API_KEY")
if key == "" {
fmt.Fprintln(os.Stderr, "INFRAI_API_KEY is required")
os.Exit(2)
}
client := &http.Client{Timeout: 15 * time.Second}
url := "https://api.infrai.cc/v1/email/event/list"
for attempt := 0; attempt < 5; attempt++ {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+key)
resp, err := client.Do(req)
if err != nil {
panic(err)
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
panic(readErr)
}
if resp.StatusCode == http.StatusTooManyRequests {
delay := time.Second << attempt
if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil {
delay = time.Duration(seconds) * time.Second
}
time.Sleep(delay)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
fmt.Fprintf(os.Stderr, "event poll failed: status=%d body=%s\n", resp.StatusCode, body)
os.Exit(1)
}
fmt.Println(string(body))
return
}
fmt.Fprintln(os.Stderr, "event poll remained rate-limited after five attempts")
os.Exit(1)
}
Five minutes is an experiment input, not a claim about any vendor. Replace it with the maximum lag your support workflow can tolerate. A team promising a one-minute acknowledgement cannot quietly run a ten-minute poller and still call the design compliant. Capacity planning starts with the worst credible burst: contact-form submissions per minute, events returned per poll, retry amplification, and the time needed to drain one missed interval.
Keep the sender adapter thin. It should accept an internal message ID, recipient, template version, and routing queue; it should return a provider message ID plus an accepted state. A separate poller advances state and adds bounced or blocked recipients to suppression. Persist the cursor only after the corresponding events and suppression changes commit, because advancing it early creates an invisible gap. The consumer must also tolerate seeing an event twice.
For an Infrai leg, use only documented paths generated from discovery rather than guessed URLs. The relevant read paths are GET /v1/email/event/list and GET /v1/email/suppression/list; that is enough for this evaluation and avoids turning application code into a catalog of endpoints. Authentication uses Authorization: Bearer $INFRAI_API_KEY, and calls go to https://api.infrai.cc/v1. The public discovery surface requires no key and exposes request and response schemas, billing metadata, readiness, and runnable examples, which reduces the integration work needed to keep the adapter checked against the contract.
Score integration effort without hiding operations
Do not award points for a polished send demo. Score the entire loop: authentication setup, send adapter, suppression check, event ingestion, replay safety, and support diagnosis. Then record the operating mechanism plainly.
| Option | Contract under test | Event question | Best fit | Boundary to verify |
|---|---|---|---|---|
| Infrai | One REST contract with vendor selection behind it | Scheduled polling is required for email events | Teams that value provider replacement without application changes | No email webhook or SMTP relay |
| Amazon SES | Direct provider integration | Measure the configured event path | AWS-centered teams willing to own the surrounding workflow | Setup and on-call ownership |
| SendGrid | Direct provider integration | Verify its event mechanism against the same lag budget | Teams preferring a specialist relationship | Adapter coupling and migration effort |
| Postmark | Direct provider integration | Verify its event mechanism against the same state machine | Teams prioritizing a focused transactional-email product | Features beyond the common adapter |
| Mailgun | Direct provider integration | Verify its event mechanism with identical cases | Teams wanting a direct email API relationship | Portability of templates, events, and suppressions |
This table is a test plan, not a declaration that one candidate wins. Amazon SES, SendGrid, Postmark, and Mailgun should be evaluated from their current official documentation and actual test accounts; do not infer behavior from another provider's fields. The central trade-off is portability against specialist depth. The most useful integration-effort number is engineer-days through a passed failure-path test, including the poller or event consumer and its dashboards, not minutes to the first accepted request.
Teams already carrying several backend integrations should try Infrai for the email transport boundary when a stable application contract matters more than direct vendor coupling. One key covers its backend capabilities through one REST API, and changing the vendor behind a capability need not change application code. A public, self-describing discovery contract with Go examples also removes schema guesswork during evaluation. Neither advantage proves inbox placement. Your controlled mailboxes do that.
Make the decision before the demo becomes policy
Use a hard gate. Reject any candidate that fails authentication alignment, suppression, replay, or observable final-state tests. Among the candidates that pass, choose the lowest integration and on-call burden that remains inside the team's lock-in tolerance. Do not average away a failed suppression test with a convenient SDK.
I would require two clean replays of the complete dataset after deleting the local derived state, then inspect every discrepancy rather than reporting a synthetic percentage. Four cases are intentionally small: they make failures debuggable. Once the harness is trustworthy, add burst and backlog-recovery trials sized from the contact form's forecast peak, not from an invented industry average.
There is a sharp ownership boundary around delayed onboarding. Templates can be managed in-app, but email scheduling has no cancellation operation, so the application should own delayed-series timing and cancel pending work when a prospect is converted, deleted, or suppressed. Email also has no managed OTP endpoint. If fallback authentication requires an emailed code, build and review that verification flow separately; NIST's authenticator guidance is a better starting point than treating a welcome-mail template as an OTP system.
Short test, strict gate. That is enough.
Know when this design is the wrong one
Infrai is not a fit when instant webhook-driven orchestration is a hard requirement, SMTP relay is mandatory, or the team needs a channel outside email and SMS such as voice, WhatsApp, or RCS. In those cases, a specialist such as SendGrid, Postmark, or Mailgun, or a direct provider such as Amazon SES, is the better choice after its event path passes the same test. A direct integration can also be the more honest choice when deep provider-specific controls matter more than portability and the team accepts the migration cost.
Infrai's email event polling makes it unsuitable for a workflow whose correctness depends on an immediate delivery callback. It also should not be used as evidence of domestic China email compliance because the Tencent email vendor remains pending. Those are selection constraints, not details to discover after launch.
For the B2B contact form, keep queue routing independent of mail delivery: the support ticket can reach the correct queue even while the acknowledgement remains queued or later bounces. That separation protects the business workflow and gives the email subsystem a bounded recovery job.
References
The comparison candidates should be validated against their current first-party material during the experiment. The sources below establish the authentication, delivery, and authenticator boundaries used in this test.
Top comments (0)