Skip to main content

The email queue (Lovable-coupled)

Email is a PGMQ-based queue dispatched by a cron worker, entirely coupled to Lovable's proprietary services.

Flow

  1. auth-email-hook — a Supabase Auth "Send Email" hook. Verifies a Lovable webhook signature (@lovable.dev/webhooks-js, headers x-lovable-signature/x-lovable-timestamp, secret = LOVABLE_API_KEY). Renders a React-Email template to HTML + plain text, writes a pending row to email_send_log (before enqueue, deliberately), then rpc('enqueue_email', { queue_name: 'auth_emails', payload }).
  2. process-email-queue — cron worker (gateway-JWT auth). Reads auth_emails then transactional_emails in priority order via read_email_batch, sends through Lovable's email API (@lovable.dev/email-js), logs sent/failed, and delete_email on success. DLQs: <queue>_dlq via move_to_dlq.

Magic constants (in process-email-queue / email_send_state)

MAX_RETRIES=5, batch_size=10, send_delay_ms=200, auth_email_ttl=15min, transactional_ttl=60min, visibility timeout vt=30s, rate-limit Retry-After=60s. Config overridable from the singleton email_send_state (id=1). On a 429 the worker writes retry_after_until and stops the whole run.

Safety nets

  • Idempotency: a partial unique index email_send_log(message_id) WHERE status='sent' plus a pre-send check handles visibility-timeout double-sends.
  • Queue RPCs are SECURITY DEFINER but REVOKE FROM PUBLIC; GRANT service_role only.

Gotchas for the rebuild (target is .NET)

  • Everything email is Lovable-proprietary — webhook lib, send API, LOVABLE_API_KEY (which doubles as webhook secret). None of it survives leaving Lovable; the queue, DLQ, TTL, idempotency, and rate-limit backoff logic must be reimplemented.
  • Leftover identifier SITE_NAME="open-whisper-hub" leaks into the From: display name (whistleblower pivot).
  • English EMAIL_SUBJECTS with Portuguese bodies.
  • The portal-submission notification email is an unimplemented console.log stub.

Rebuild implication

Reimplement on the target stack (e.g. a .NET background worker + a real ESP) preserving the queue semantics (priority, retry/DLQ, TTL, idempotency, rate-limit backoff) and the pending-before-send audit row.