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>
12 lines
641 B
PL/PgSQL
12 lines
641 B
PL/PgSQL
-- Existing PostgreSQL installations: pause enqueue and dispatch before applying.
|
|
-- SHA-256 is PostgreSQL's built-in bytea function; no extension is required.
|
|
BEGIN;
|
|
ALTER TABLE email_message ADD COLUMN rfc_message_id VARCHAR(500);
|
|
UPDATE email_message
|
|
SET rfc_message_id = '<' || left(encode(sha256(convert_to(
|
|
coalesce(idempotency_key, 'qbit-email:' || id::text), 'UTF8')), 'hex'), 32)
|
|
|| '@' || coalesce(lower(substring(from_address from
|
|
'@([A-Za-z0-9]+(?:[.-][A-Za-z0-9]+)*)(?:>|$)')), 'qbit-email.local') || '>';
|
|
ALTER TABLE email_message ADD CONSTRAINT email_message_rfc_message_id_unique UNIQUE (rfc_message_id);
|
|
COMMIT;
|