fix(email): query documents table for settings + bind fetch on Workers (#1098 #1099)

LA
3d ago
+725-127

Problems fixed

#1098 — Email plugin settings never loaded

loadDbEmailSettings and sendViaEmailPlugin (in auth/config.ts) both queried:

SELECT settings FROM plugins WHERE id = 'email'

The v2 plugins table no longer exists on greenfield v3 installs. The query silently threw (caught) and returned null, so email was never configured from the admin UI — every send fell back to the console provider.

Fix: Both now read from the documents table:

SELECT data FROM documents
WHERE type_id = 'plugin' AND slug = 'email'
  AND is_current_draft = 1 AND deleted_at IS NULL

Also handles resendApiKey (current field name) with apiKey as fallback for older installs.

#1099 — ResendProvider / SendGridProvider crash with "Illegal invocation" on Workers

Both providers stored a reference to the global fetch:

this.fetchImpl = options.fetchImpl ?? fetch  // ← unbound

On Cloudflare Workers, calling a stored fetch reference outside its original binding context throws Illegal invocation.

Fix: fetch.bind(globalThis) preserves the binding:

this.fetchImpl = options.fetchImpl ?? fetch.bind(globalThis)

Files changed

  • packages/core/src/services/email/db-settings.ts — documents table query
  • packages/core/src/auth/config.ts — documents table query + resendApiKey support
  • packages/core/src/services/email/providers/resend.ts — fetch.bind(globalThis)
  • packages/core/src/services/email/providers/sendgrid.ts — fetch.bind(globalThis)

Closes #1098
Closes #1099

RetriggerView in GreptileConfidence Score: 4/5

Existing blank email documents can still hide working credentials, and the two outstanding repository requirements must be addressed before merging.

Findings

  1. P1 Saved email credentials are ignored ▶
  2. P2 Boot recreates forbidden plugin storage ▶
  3. P2 Forbidden plugin table returns ▶
  4. P2 Route bypasses document services ▶

Summary

The PR makes email settings readers prefer the global plugin document while keeping legacy reads.

  • Admin email settings now reach email and auth sends.
  • Resend and SendGrid keep their fetch binding on Workers.
  • The reporting test checks its baseline without hiding other config changes.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Read email settings] --> B{Valid global document settings?}
  B -->|Yes, including empty object| C[Use document settings]
  B -->|No| D[Read legacy settings]
  E[Save email settings] --> F{Global document exists?}
  F -->|Yes| G[Replace document settings]
  F -->|No| H[Update legacy settings]

Reviews (4) · Last reviewed commit: "fix(email): type Cloudflare settings use..." · Reviewed by Greptile