EmailApi.sendOnce(request, effectKey) with EmailApiEffectOutcome and
EmailApiEffectResult, lookups by idempotency key and RFC Message-ID, and
rfcMessageId on EmailApiMessage, so other qbits have one public surface.
EmailEffects and its types stay as internal, deprecated delegates; the
durable-jobs guide, README and DESIGN 2.5 point at EmailApi.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
com.kingsrook.qbits.email.api is the stable contract for other qbits:
EmailApi (isInstalled, send, ensureTemplate, message lookups by id and
idempotency-key prefix with metadata only, sender addresses, default
provider, readiness per category) with its own request, result,
template, message and readiness types. A reflection test keeps internal
types out of every public signature. The README and DESIGN 2.5 document
the two supported routes: core SendMessageAction with the qbitEmail
provider for plain mail, and the api package for the rest; internal
packages are not API.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For the durable jobs outbox (QRun-IO/qqq#1191, spec section 2.13):
- Each queued message stores one RFC 5322 Message-ID (email_message.rfc_message_id,
unique), derived from the idempotency key (else a stable per-message seed),
and reuses it on every attempt. SMTP, Postmark, SendGrid and Mailgun send it.
SES receives it in the raw MIME but replaces it; this is documented, and
X-QQQ-Email-Id stays on every transport.
- EmailEffects.send(request, effectKey) hands an email to qbit-email's outbox
exactly once per key: QUEUED_OR_DUPLICATE, or REFUSED (suppressed or
invalid; never retried).
- findByIdempotencyKey / findByRfcMessageId look an email up for a reconcile.
- docs/DURABLE-JOBS.md has the outcome mapping and the binding class to add
when QQQ RC.7 ships (EmailJobEffectTarget implements core's EffectTarget;
no SNAPSHOT dependency now).
- Postgres upgrade SQL for existing installs; checkstyle now also covers test
sources (the repo standard), with the existing violations fixed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
email_provider_sender_address (child of the provider; admin-only;
domain, uniqueness and single-default checks). Sends may name a sender
row (withFromAddressId) or match one by text; rows belong to the
resolved provider, the default row wins, and the provider's from
address stays the fallback. Message rows record from_address_id.
Contingent possible-value filters: fromAddressId by providerId on both
send processes, on Send Test Email (seeded from the acted-on provider)
and on email_message; message ids on attempts and events by provider;
suppression source event by source message. One test per pair.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in phase (b); README and CHANGELOG combine both, DESIGN 7.3 keeps
the ClassifiedValueTokens wording with the env1 key id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Webhook inbox rows apply matched events independently; unmatched
events retry, then are skipped with a note instead of failing the row.
- Notification and marketing messages are never deleted by retention,
so unsubscribe links keep working; their bodies are still cleared.
- Events only suppress recipients of the matched message; an SES
bounce without recipients no longer suppresses every destination.
- SNS notifications outside a 1 h / +5 min window are refused, and
failed certificate fetches are cached for 5 minutes.
- EmailTemplateDefinition and EmailTemplates.ensure let other qbits
register their templates once without overwriting edits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps the polished home layout with phase (c)'s event-backed metrics.
Also fixes unsubscribe privacy: a message with an unsubscribe link goes
to exactly one recipient, its token binds that address, and the handler
suppresses only that address (DESIGN 8.2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase (c) of docs/DESIGN.md: the email_webhook_inbox and email_event
tables; a /qqq/hooks/email route provider with SES (SNS signature and
certificate host rules, subscription confirmation), Postmark (basic
auth), SendGrid (ECDSA) and Mailgun (HMAC with replay protection)
verification into a durable inbox; a claim-safe inbox processor that
maps provider events to email_event rows, message status and
suppressions; RFC 8058 one-click unsubscribe with a confirmation page;
the Reprocess action; and event-backed home metrics.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase (a) part 2 of docs/DESIGN.md: the variable engine with escaping,
if/each and fallbacks; variable schemas; Markdown in the branded
responsive layout with dark-mode colours and contrast checks; HTML and
MJML kinds (MJML through a pluggable compiler at activation); versions
with New Version, Activate Version and Approve For PHI; templated sends
with record variables read as the sender; the classification stand-in
(core #1142); PII/PHI refusal; redacted variable snapshots with
ClassifiedValueTokens-shaped tokens and encrypted PHI bodies (stand-ins
for core #1161); the secure-message built-in; the preview widget; the
home dashboard; contingent possible values; and the canary-PHI egress
test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
D11 records the owner rule that only the database and S3 hold data.
Section 7.3 follows secured-data section 14.5 (record-field and
domain-prefixed bindings, changed:v1 for low-entropy context values).
Section 8.3 uses UserPreferenceRequestContext.getUserEmailAddress().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outbox on core's messaging SPI, providers as data rows (SMTP, SES,
Postmark, SendGrid, Mailgun, Gmail), Markdown and MJML/HTML templates
with versions and dark-mode-safe branding, delivery tracking through
signed webhooks, suppression, RFC 8058 unsubscribe, PHI rules, consumer
migrations and the inbound phase. Owner decisions (2026-10-12): all
recommendations accepted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apache-2.0 LICENSE and NOTICE, community pointer files, CHANGELOG,
CLAUDE.md and AGENTS.md, Maven wrapper, Checkstyle, dependabot,
CircleCI (qqq-orb 0.6.8, configure-package-install pre-step, GA-only
publish_release), the release-rc caller workflow, and a minimal
EmailQBitProducer and EmailQBitConfig on qbit-build-parent 2.0.0 with
the QQQ 4.1 BOM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>