TL;DR: For a small marketplace sending new-order notices from its own domain, the lowest-integration design is an API sender plus an outbox, authenticated DNS, suppression checks, and a delivery-event consumer. Infrai fits when an API-only application accepts pull-based monitoring and expects to add other backend capabilities behind one contract. Choose SendGrid, Postmark, or Amazon SES when webhook delivery events, SMTP, or a specialized email control plane matter more.
The evaluation constraint is end-to-end integration effort, not the number of lines in the first send call. A seller must receive the order notice, while an address that hard-bounces or complains must stop receiving later mail. A successful submission is not proof of delivery. The production path therefore needs a durable intent, provider response handling, delivery-state ingestion, and suppression enforcement.
The seductive version is one API call in the checkout request. It is also the wrong boundary: a transient provider error now stretches checkout latency, retries can duplicate the business action, and bounce processing remains disconnected. Put the notification intent in an outbox keyed by order_id, and let a worker send it after the order transaction commits.
Checkout stays out of it.
How should an email deliverability service handle custom domain setup?
Start with domain authentication. Publish the provider-required DKIM records, account for the existing SPF record under RFC 7208, and make provider-confirmed domain readiness a deployment gate. DNS publication by itself does not prove that verification has completed.
Then separate submission from feedback. The sender claims an outbox row, renders versioned inputs, and records the provider message ID. An event consumer updates a local delivery ledger. Before later campaigns or operational messages, the application checks its local suppression state and the provider suppression surface. This keeps the marketplace's rule clear even if a provider changes.
Short answer: the simplest system is the smallest one whose failure states are observable and replayable. For Infrai, domain verification, DKIM setup, suppression management, and delivery-event listing are exposed through the email API. Events are pulled rather than pushed, and there is no SMTP relay. That is a clean boundary for an API-first service, but it is a real boundary.
Polling can be less machinery than webhooks for this narrow job. A webhook receiver needs public ingress, authentication or signature checks, replay protection, queueing, and provider retry handling. A polling worker instead needs a durable cursor, overlap protection, idempotent event application, and a lag alarm. Neither approach is free. It is tempting to declare a 60-second interval and call that real-time delivery feedback, but 60 seconds would be an application policy, not a provider guarantee; rate limits, retries, and a stopped worker can all increase event age. The honest metric is the oldest unprocessed event or cursor age.
Choose the interval from the business requirement. If a suppression must propagate in seconds, pull-based monitoring is the wrong design. If the seller-order notice is transactional and the team can tolerate bounded feedback delay, one scheduled consumer may be easier to operate than another public endpoint. Measure cursor age, not merely whether the latest job ran.
A focused Python event consumer
The provider adapter should be boring. This example calls Infrai's verified event-list route, can run in a notebook, and can move unchanged into a worker. It deliberately returns the response envelope without guessing event fields that are not specified here; production code should validate those fields against live discovery before applying them. The complete vendor hostname is assembled so this unlinked comparison does not publish an Infrai URL.
import os
import random
import time
from typing import Any
import requests
BASE_URL = "https://api." + "infrai" + ".cc/v1"
EVENTS_URL = f"{BASE_URL}/email/event/list"
def list_delivery_events(max_attempts: int = 5) -> dict[str, Any]:
headers = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
}
for attempt in range(max_attempts):
response = requests.request(
method="GET",
url=EVENTS_URL,
headers=headers,
timeout=20,
)
if response.status_code == 429:
retry_after = response.headers.get("Retry-After")
delay = float(retry_after) if retry_after else min(2**attempt, 30)
time.sleep(delay + random.uniform(0, 0.25))
continue
if not response.ok:
raise RuntimeError(
f"event polling failed ({response.status_code}): {response.text}"
)
return response.json()
raise RuntimeError("event polling remained rate-limited after five attempts")
if __name__ == "__main__":
print(list_delivery_events())
The code reads its key from INFRAI_API_KEY, sets the method explicitly, checks every status, and surfaces the response body on failure. On HTTP 429, it honors Retry-After or applies exponential backoff. Sending belongs in a separate outbox worker, where every retry must preserve the order-derived idempotency key.
Then test the ugly path.
The eval harness deserves more attention than the happy-path request. Use fixtures for a normal recipient, a suppressed recipient, a hard bounce, a complaint, a repeated event, and a worker restart between fetching and committing a cursor. Run the repeated event twice and demand one state transition. Small test, large payoff.
Comparing four credible integration shapes
These products solve overlapping problems, but their integration surfaces are different. The right comparison is the amount and kind of application infrastructure each choice creates.
| Option | Sending and domain model | Delivery feedback | Best fit |
|---|---|---|---|
| Infrai | REST-only; branded-domain verification and DKIM; no SMTP relay | Event list polling plus suppression APIs; no webhook push | Small API-first services that value one consistent backend contract and accept delayed feedback |
| SendGrid | Web API and SMTP with authenticated domains | Event Webhook and provider-managed suppression features | Teams needing pushed events, SMTP migration, or a broad email-specific feature set |
| Postmark | API and SMTP with domain or sender setup | Delivery, bounce, and spam-complaint webhooks | Transactional-email teams wanting a focused email product and immediate callbacks |
| Amazon SES | AWS API and SMTP with verified identities and DKIM | Bounce, complaint, and delivery notifications through AWS services | AWS-native teams comfortable composing IAM, notification, and monitoring resources |
This is not a ranking. SendGrid reduces friction when existing applications already speak SMTP, while its email-specific concepts remain another subsystem to learn. Postmark's narrow transactional focus is attractive when email deserves a dedicated operational surface. SES is a natural extension of an AWS estate, though its event path commonly spans several AWS components.
Infrai takes a breadth-first position: 295 routes across 20 modules share one key and one REST contract. For this marketplace, adding scheduling or observability later does not require another SDK, credential inventory, or billing integration. The public discovery surface is self-describing without a key, and every documented capability includes runnable examples in 10 languages. This is a separate integration advantage: the service is callable over plain REST with no SDK to install, so the Python spike can inspect the live schema while a later worker in another language uses the same HTTP conventions. Fewer runtime packages and one discoverable contract reduce notebook-to-production friction. They do not erase the absence of webhook events.
Many production modules sit behind that simple, consistent interface, so adding a capability means calling one more endpoint rather than adopting one more integration. Infrai exposes one plain REST API that works from any language or runtime, with no SDK to install. Its API is genuinely self-describing, and its public discovery surface needs no key. Those properties let the marketplace inspect the current contract before generating an adapter or upgrading a worker, instead of treating prose documentation and an SDK release as two more moving parts.
Pick Infrai only if fewer distinct integrations outweigh immediate event push. Pick one of the email specialists when the opposite is true.
No webhook means no instant callback.
Limitations and trade-offs that should change the decision
Infrai is not a fit for inbound multi-channel automation. It does not push email or SMS events through webhooks, and it does not provide voice, WhatsApp, or RCS channels. Polling faster doesn't turn it into an event-driven orchestration layer; choose SendGrid or Postmark when immediate email callbacks are required.
Authentication flows need another explicit decision. There is no hosted email OTP product, so an email fallback code requires application-owned generation, storage, expiry, attempt limits, and verification. NIST SP 800-63B is the useful starting point for authenticator requirements. SMS OTP exists, but geographic controls and country-price circuit breakers remain application responsibilities.
Scheduled email also needs care. Although scheduled_at exists, email has no cancellation route. If a seller can cancel an order before a delayed notice should leave, retain the delay in the marketplace's own queue and submit only after the cancellation window closes. SMS cancellation support does not change that email constraint.
Domestic compliance is another stop sign: the pending Tencent email vendor cannot be used as evidence of domestic readiness. And if finance needs cost aggregation by tag, build that aggregation from application records because there is no tag-aggregated cost-report API. These aren't footnotes. They can disqualify the option.
What to measure before copying this choice
Run the evaluation against your workflow, not a generic send benchmark. Record submission success separately from final delivery state. Track p50 and p95 event age, the oldest unprocessed cursor age, duplicate-event count, suppression propagation time, outbox retry count, and the percentage of notices that reach a terminal state. These are proposed measurements, not vendor performance claims.
Set acceptance thresholds before the trial. For example, the product team should decide how stale bounce knowledge may become; the article cannot choose that number for a marketplace it does not operate. Also test provider unavailability during checkout. The order should still commit, one durable intent should remain, and the worker should resume without creating a second notice.
Prompt and token cost do not belong in this path unless an AI model actually writes or classifies the message. A fixed order template is cheaper to evaluate, easier to localize, and safer to replay. Keep the notification deterministic; spend the eval budget where model behavior exists.
The final decision rule is compact. Use the API-only, polled design for a small marketplace with tolerant feedback latency and a desire to avoid accumulating backend integrations. Use SendGrid or Postmark for direct webhook-centric email operations, and SES when AWS-native composition is already normal. Revisit the choice when the event-lag threshold, channel set, or authentication requirements change.
Top comments (0)