# Pathrule Pattern: Email Delivery and SMTP (1.0.0)
# ::pathrule:package:email-delivery-smtp

### [RULE] Give every logical email a stable idempotency key  (path: /src/workers)
<!-- scope: folder | priority: high | strict -->

Queues and providers can retry after timeouts or ambiguous responses. A worker that creates a new message identity on every attempt can send duplicate password links, invoices, or alerts.

- Construct a stable logical key from the domain event and recipient, adding an occurrence or template version only when the product intends a distinct message.
- Store message state before provider submission and return the prior provider identifier or terminal outcome when the same key is processed again.
- Separate retry attempts from logical messages so delivery history preserves one intent with several transport attempts.
- For bulk or scheduled mail, generate recipient-level identities and checkpoint progress; do not make one failure replay every recipient.

See /src/email for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Authenticate the exact sending domains and streams  (path: /ops/email)
<!-- scope: folder | priority: high | strict -->

Mailbox providers evaluate domain identity and reputation across several signals. A valid SMTP credential does not prove that the chosen domain authorizes or aligns with the sender.

- Inventory transactional, marketing, support, and test streams and assign approved From, return-path, and signing domains without sharing production reputation with uncontrolled environments.
- Publish SPF authorization without creating duplicate records or exceeding lookup behavior, and remove providers when they no longer send.
- Enable DKIM with managed or rotated selectors and verify signatures on received messages, not only provider-console status.
- Introduce DMARC reporting and policy in stages, reviewing legitimate sources and alignment before moving to stronger enforcement.

See /ops/email for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Enforce suppression, consent, and message classification before send  (path: /src/email)
<!-- scope: folder | priority: high | strict -->

Unsubscribe, complaint, bounce, consent, and account-security policies differ by message purpose. A generic send function that ignores classification can either suppress critical account mail or continue unwanted promotional delivery.

- Classify templates and domain events at definition time and require the classification in the send command.
- Check hard-bounce, complaint, global suppression, product subscription, and jurisdiction-specific consent state before provider submission.
- Keep transactional messages limited to the requested service purpose; adding promotional content can change the applicable policy and recipient expectation.
- Provide one reviewed override path for legally or operationally required communication and record why the suppression decision was bypassed.

See /src/workers for the adjacent decision or procedure that completes this constraint.

---

### [MEMORY] Provider acceptance is one delivery state  (path: /src/email)

An API success or SMTP acceptance means the provider took responsibility for the message, not that the mailbox accepted or displayed it. Product behavior must not treat all later outcomes as success.

- Store provider message identity and correlate signed provider events to the logical email without trusting an arbitrary callback payload.
- Classify temporary deferrals separately from permanent recipient or policy failures and cap automatic retries by the provider contract.
- Move hard bounces and complaints into suppression promptly while retaining enough reason and timestamp data for support and reputation work.
- Expose delivery status to product workflows only at the confidence they need; for example, account recovery may offer another channel without claiming the recipient read the mail.

See /src/workers for the rule or workflow that puts this decision into practice.

---

### [MEMORY] Templates are versioned data contracts  (path: /src/email)

A template change can break rendering, accessibility, localization, tracking, or the security meaning of a link even when the send API remains unchanged. Treat the template and variable schema as one versioned contract.

- Validate required variables and types before enqueue so workers do not discover a missing value after the business transaction has committed.
- Generate text and HTML alternatives from the same semantic content and test escaping, long values, localization, and client-safe layout.
- Put opaque, bounded, expiring tokens in action links and resolve state on the server; do not embed secrets, personal records, or authorization decisions in query strings.
- Record template version with the logical message so support can reproduce what the recipient was sent without retaining unnecessary rendered personal content.

See /ops/email for the rule or workflow that puts this decision into practice.

---

### [SKILL] verify-email-delivery-flow  (path: /)

---
name: verify-email-delivery-flow
description: Verify an email type or provider integration before production rollout.
---

# Verify Email Delivery Flow

Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result.

- [ ] Generate representative messages for success, duplicate event, missing variable, invalid address, suppressed recipient, and provider timeout using stable logical keys.
- [ ] Inspect received headers for From, return path, DKIM, SPF, DMARC alignment, Message-ID, list headers where relevant, and unintended environment leakage.
- [ ] Replay signed accepted, deferred, bounced, complained, and malformed provider events and confirm state transitions are idempotent and attributable.
- [ ] Render text and HTML in representative clients with long localized content, images disabled, dark mode, and assistive technology expectations.
- [ ] Search logs, traces, metrics, URLs, and dead-letter payloads for message bodies, tokens, email addresses, and other data the observability contract excludes.

## Exit criteria

The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks.

---

### [SKILL] rotate-email-sending-domain  (path: /)

---
name: rotate-email-sending-domain
description: Change an email provider, sending subdomain, DKIM selector, return path, or DMARC policy.
---

# Rotate Email Sending Domain

Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result.

1. Inventory every legitimate sender, stream, domain, provider credential, DNS record, webhook, suppression source, and application configuration involved.
2. Publish and verify new SPF, DKIM, return-path, and tracking records while keeping old records active for mail still in flight.
3. Send controlled traffic through the new path, inspect authentication and feedback events, and increase volume only while bounce, complaint, and deferral signals remain healthy.
4. Synchronize suppression and unsubscribe state before moving recipients; never warm a new provider by resending to addresses the old provider suppressed.
5. Retain rollback capability until queued mail and feedback on the old path drain, then remove obsolete credentials and DNS authorization deliberately.

## Exit criteria

The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks.
