A sent response is weak evidence for a logistics report attachment. The real choice is between a managed delivery API with exportable event records and a self-operated mail pipeline with records you control. Choose the path that can reconstruct authentication, attachment identity, and bounce decisions per message; use the same controls for password-reset mail on your custom domain.
Accepted isn't delivered.
| Path | Evidence to retain | Operational burden |
|---|---|---|
| Managed API | Request ID, attachment digest, accepted response, verified events, durable export | Verify event coverage, retention, and regional boundaries |
| Self-operated pipeline | Queue, signing configuration, SMTP replies, delivery-status notifications | Own queue health, retries, DNS, and evidence retention |
Short answer: prefer neither path by brand. Run a documented failure drill in both US and EU deployments, and select the one whose evidence trail survives a delayed bounce and an audit request. A provider acceptance event is not proof that a mailbox displayed the message.
What can an auditor actually verify?
Start with a report ID, recipient reference, region, generation timestamp, and SHA-256 digest of the exact bytes attached. Store the digest and internal correlation ID before enqueueing. Store the response and subsequent delivery events separately. Never put the reset token, the report body, or an attachment in an event log. If retention rules require a copy of the report, place it in the governed document store and link the audit record to its immutable identifier; email is the transport, not the archive.
The same separation matters for password resets. A 2xx API response means the API accepted a request, not that the recipient received a usable link. Treat hard-bounce suppression as a state transition, not a reason to silently mark an account unreachable forever. Define a reviewed recovery path that checks the address and requires fresh authorization before removing a suppression. Soft failures deserve a bounded retry policy; indefinite retries turn a temporary problem into an opaque queue.
How should a custom domain email deliverability setup handle password reset bounces?
First, authenticate the visible sending identity. Publish SPF for the actual sending infrastructure, configure DKIM signing for the custom domain, and set a DMARC policy with reporting so alignment can be checked. Google's sender guidelines describe authentication and alignment expectations; RFC 7489 defines how DMARC evaluates identifiers. DNS publication alone proves little. Inspect the headers of a received test message in each region and record the authentication results and signing domain.
Second, map delivery outcomes to actions. SMTP reply codes distinguish transient from permanent failures under RFC 5321; enhanced status codes add detail under RFC 3463. A permanent address failure should stop repeated sends to that address, while a transient failure can be retried with a cap and an alert when its queue age exceeds the reset-link lifetime. This is a policy decision: a password reset should never arrive after its token expires and be counted as a successful user recovery. Keep the original SMTP status or provider event payload alongside the normalized classification. Classification without raw evidence is hard to challenge later.
For report attachments, add a pre-send size check against the selected transport's documented limit. MIME encoding expands binary payloads, so checking only the source file size is insufficient (RFC 2045). If the attachment is too large, stop and route it through an approved document-access workflow; do not substitute an ungoverned public link.
The trade-off is audit detail versus operational exposure. Imagine the report request times out after enqueueing, then a bounce event arrives before the retry receives an acceptance ID. Correlating by the second request's ID alone would lose the original failure; retrying without an idempotency key could send a duplicate attachment. Retain the original request ID, queue state, and terminal event together. A reset message has an additional deadline: once its link expires, further delivery attempts no longer help the account holder, even if the mail system eventually classifies the send as successful.
What does a small implementation boundary look like?
Keep the integration contract narrow. This TypeScript example emits an audit-ready request without pretending that the returned acceptance ID is a delivery receipt. The transport and event store remain replaceable.
import { createHash } from "node:crypto";
type MailRequest = {
recipient: string;
reportId: string;
region: "US" | "EU";
attachment: Buffer;
};
type Acceptance = { messageId: string; acceptedAt: string };
type MailTransport = {
send(request: MailRequest & { correlationId: string }): Promise<Acceptance>;
};
type AuditStore = { append(record: Record<string, unknown>): Promise<void> };
async function submitReport(
request: MailRequest,
correlationId: string,
transport: MailTransport,
audit: AuditStore,
): Promise<void> {
const digest = createHash("sha256").update(request.attachment).digest("hex");
await audit.append({ correlationId, reportId: request.reportId, region: request.region, digest, state: "queued" });
const acceptance = await transport.send({ ...request, correlationId });
await audit.append({ correlationId, messageId: acceptance.messageId, acceptedAt: acceptance.acceptedAt, state: "accepted" });
}
The example deliberately does not log the recipient. In a production system, keep a protected recipient reference in the audit store so authorized staff can investigate without spreading addresses across telemetry. Also make the enqueue operation idempotent by report ID and recipient reference: a retry after a timeout must not quietly send two copies. Reconcile accepted messages against asynchronous events, including events that arrive out of order. Measure time from enqueue to terminal classification by region, rather than presenting one global success percentage.
When is the runner-up the better choice?
A self-operated pipeline earns its extra work when policy requires direct control of signing keys, event retention, and regional storage, and the team can staff deliverability and queue operations. A managed API earns its place when it provides independently verifiable events and the team needs a short path from integration to a tested failure drill. Neither removes responsibility for suppression review, account recovery, or report retention. A managed service is unsuitable when its event export cannot satisfy the required retention period or residency boundary; running your own mail system is unsuitable when nobody owns its queues and authentication monitoring.
Neither choice guarantees inbox placement. That's a limitation of treating delivery events as the whole user experience; a received test message and an actual reset completion are separate signals.
Before rollout, test a valid inbox, a permanently invalid address, an artificial transient failure, an expired reset token, duplicate submission, and a report over the transport limit. Preserve the request correlation ID through each test. Check where event data lives and how it can be exported before choosing a regional deployment. That evidence is more useful than a setup screen that says DKIM is enabled.
References
- Google, Email sender guidelines: https://support.google.com/a/answer/81126
- RFC 7489, Domain-based Message Authentication, Reporting, and Conformance: https://www.rfc-editor.org/rfc/rfc7489
- RFC 5321, Simple Mail Transfer Protocol: https://www.rfc-editor.org/rfc/rfc5321
- RFC 3463, Enhanced Mail System Status Codes: https://www.rfc-editor.org/rfc/rfc3463
- RFC 2045, MIME Part One: https://www.rfc-editor.org/rfc/rfc2045
Top comments (0)