cloudflare-email 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +149 -1
- data/README.md +287 -385
- data/SECURITY.md +51 -0
- data/app/controllers/cloudflare/email/ingress_controller.rb +33 -21
- data/app/controllers/cloudflare/email/management/mailboxes_controller.rb +173 -0
- data/app/controllers/cloudflare/email/management/styles_controller.rb +13 -0
- data/app/views/cloudflare/email/management/mailboxes/index.html.erb +65 -0
- data/app/views/cloudflare/email/management/mailboxes/message.html.erb +34 -0
- data/app/views/cloudflare/email/management/mailboxes/show.html.erb +86 -0
- data/app/views/layouts/cloudflare/email/management.html.erb +29 -0
- data/docs/activerecord-tenanted.md +181 -0
- data/docs/architecture.md +105 -0
- data/docs/custom-ingress.md +207 -0
- data/docs/delivery-events.md +186 -0
- data/docs/features.md +138 -0
- data/docs/getting-started.md +308 -0
- data/docs/mailboxes.md +363 -0
- data/docs/management-engine.md +190 -0
- data/docs/outbox.md +175 -0
- data/docs/routing-deliveries.md +94 -0
- data/docs/routing-diagnostics.md +68 -0
- data/docs/tenant-mailboxes-plan.md +149 -0
- data/docs/thread-correlation.md +27 -0
- data/docs/troubleshooting.md +104 -0
- data/docs/upgrading-0.2.md +101 -0
- data/docs/upgrading-0.3.md +55 -0
- data/docs/verification/2026-09-10-followup.md +49 -0
- data/docs/verification/2026-09-10-install-upgrade.md +86 -0
- data/docs/verification/2026-09-10-live.md +102 -0
- data/docs/verification/2026-09-10.md +175 -0
- data/docs/verification/2026-09-11-custom-ingress.md +49 -0
- data/docs/verification/2026-09-11-extraction.md +32 -0
- data/docs/verification/2026-09-11-outbound-ledger.md +60 -0
- data/docs/verification/2026-09-11-security.md +76 -0
- data/docs/verification/2026-09-11-tenant-mailboxes.md +75 -0
- data/docs/verification/2026-09-12-destination-context.md +46 -0
- data/docs/verification/2026-09-13-durable-inbound-and-routing.md +71 -0
- data/examples/plain_ruby.rb +24 -0
- data/lib/cloudflare/email/active_record/base.rb +60 -0
- data/lib/cloudflare/email/active_record/delivery_events.rb +72 -0
- data/lib/cloudflare/email/active_record/event_inbox.rb +77 -0
- data/lib/cloudflare/email/active_record/event_receipt.rb +17 -0
- data/lib/cloudflare/email/active_record/mail_snapshot.rb +24 -0
- data/lib/cloudflare/email/active_record/outbound_delivery.rb +22 -0
- data/lib/cloudflare/email/active_record/outbound_recipient.rb +13 -0
- data/lib/cloudflare/email/active_record/outbound_reconciliation.rb +15 -0
- data/lib/cloudflare/email/active_record/outbox.rb +219 -0
- data/lib/cloudflare/email/active_record/outbox_notifications.rb +34 -0
- data/lib/cloudflare/email/active_record/routing_deliveries.rb +128 -0
- data/lib/cloudflare/email/active_record.rb +5 -0
- data/lib/cloudflare/email/check_route_task.rb +21 -0
- data/lib/cloudflare/email/client.rb +93 -18
- data/lib/cloudflare/email/consume_events_task.rb +22 -0
- data/lib/cloudflare/email/delivery_event.rb +70 -0
- data/lib/cloudflare/email/delivery_method.rb +5 -0
- data/lib/cloudflare/email/deploy_worker_task.rb +6 -3
- data/lib/cloudflare/email/dev_ingress_guard.rb +27 -0
- data/lib/cloudflare/email/dev_tunnel.rb +31 -5
- data/lib/cloudflare/email/doctor.rb +16 -38
- data/lib/cloudflare/email/endpoint.rb +24 -0
- data/lib/cloudflare/email/engine.rb +33 -0
- data/lib/cloudflare/email/envelope.rb +58 -0
- data/lib/cloudflare/email/event_consumer.rb +95 -0
- data/lib/cloudflare/email/ingress.rb +115 -0
- data/lib/cloudflare/email/mailboxes/configuration.rb +58 -0
- data/lib/cloudflare/email/mailboxes/events.rb +112 -0
- data/lib/cloudflare/email/mailboxes/inbound_retention.rb +14 -0
- data/lib/cloudflare/email/mailboxes/jobs.rb +34 -0
- data/lib/cloudflare/email/mailboxes/models.rb +165 -0
- data/lib/cloudflare/email/mailboxes/provider_correlation.rb +11 -0
- data/lib/cloudflare/email/mailboxes/service.rb +372 -0
- data/lib/cloudflare/email/mailboxes/shared_event_receipt.rb +14 -0
- data/lib/cloudflare/email/mailboxes.rb +11 -0
- data/lib/cloudflare/email/management/adapter.rb +31 -0
- data/lib/cloudflare/email/management/configuration.rb +17 -0
- data/lib/cloudflare/email/management/engine.rb +15 -0
- data/lib/cloudflare/email/management/management.css +68 -0
- data/lib/cloudflare/email/management/routes.rb +14 -0
- data/lib/cloudflare/email/management.rb +7 -0
- data/lib/cloudflare/email/message_id.rb +12 -0
- data/lib/cloudflare/email/provider_metadata.rb +77 -0
- data/lib/cloudflare/email/provision_catchall_task.rb +4 -4
- data/lib/cloudflare/email/provision_route_task.rb +2 -1
- data/lib/cloudflare/email/replay_events_job.rb +18 -0
- data/lib/cloudflare/email/response.rb +21 -3
- data/lib/cloudflare/email/routing_analytics.rb +196 -0
- data/lib/cloudflare/email/routing_diagnostics.rb +206 -0
- data/lib/cloudflare/email/routing_provisioner.rb +71 -45
- data/lib/cloudflare/email/send_job.rb +41 -0
- data/lib/cloudflare/email/send_test.rb +5 -29
- data/lib/cloudflare/email/signing.rb +2 -2
- data/lib/cloudflare/email/tenancy.rb +78 -0
- data/lib/cloudflare/email/tenant_job_context.rb +90 -0
- data/lib/cloudflare/email/verification.rb +38 -8
- data/lib/cloudflare/email/version.rb +1 -1
- data/lib/cloudflare/email/worker_deployer.rb +41 -8
- data/lib/cloudflare-email.rb +4 -1
- data/lib/generators/cloudflare/email/install_generator.rb +53 -37
- data/lib/generators/cloudflare/email/mailboxes/catch_all/catch_all_generator.rb +21 -0
- data/lib/generators/cloudflare/email/mailboxes/catch_all/templates/add_cloudflare_email_catch_all.rb +18 -0
- data/lib/generators/cloudflare/email/mailboxes/mailboxes_generator.rb +55 -0
- data/lib/generators/cloudflare/email/mailboxes/templates/create_cloudflare_email_mailboxes.rb +58 -0
- data/lib/generators/cloudflare/email/mailboxes/templates/create_cloudflare_email_receiving_domains.rb +16 -0
- data/lib/generators/cloudflare/email/mailboxes/templates/create_cloudflare_email_shared_events.rb +35 -0
- data/lib/generators/cloudflare/email/outbox/outbox_generator.rb +28 -0
- data/lib/generators/cloudflare/email/outbox/templates/create_cloudflare_email_outbox.rb +48 -0
- data/lib/generators/cloudflare/email/routing_tracking/routing_tracking_generator.rb +28 -0
- data/lib/generators/cloudflare/email/routing_tracking/templates/create_cloudflare_email_routing_delivery_receipts.rb +22 -0
- data/lib/generators/cloudflare/email/templates/initializer.rb +3 -3
- data/lib/generators/cloudflare/email/templates/main_mailbox.rb +2 -7
- data/lib/generators/cloudflare/email/tracking/templates/create_cloudflare_email_event_receipts.rb +22 -0
- data/lib/generators/cloudflare/email/tracking/tracking_generator.rb +26 -0
- data/lib/tasks/cloudflare_email.rake +42 -4
- data/lib/tasks/cloudflare_email_diagnostics.rake +11 -0
- data/templates/deploy-to-cloudflare/.dev.vars.example +3 -0
- data/templates/deploy-to-cloudflare/.gitignore +6 -0
- data/templates/deploy-to-cloudflare/LICENSE.txt +21 -0
- data/templates/deploy-to-cloudflare/README.md +84 -0
- data/templates/deploy-to-cloudflare/package-lock.json +2627 -0
- data/templates/deploy-to-cloudflare/package.json +36 -0
- data/templates/deploy-to-cloudflare/src/index.js +445 -0
- data/templates/deploy-to-cloudflare/test/durable.test.ts +193 -0
- data/templates/deploy-to-cloudflare/test/index.test.ts +309 -0
- data/templates/deploy-to-cloudflare/test/relay.test.ts +226 -0
- data/templates/deploy-to-cloudflare/vitest.config.ts +8 -0
- data/templates/deploy-to-cloudflare/wrangler.toml +22 -0
- data/templates/worker/README.md +231 -16
- data/templates/worker/docs/durable-inbound.md +149 -0
- data/templates/worker/package-lock.json +2627 -0
- data/templates/worker/package.json +8 -5
- data/templates/worker/scripts/wrangler.mjs +16 -0
- data/templates/worker/src/index.js +397 -25
- data/templates/worker/test/durable.test.ts +193 -0
- data/templates/worker/test/index.test.ts +183 -13
- data/templates/worker/test/relay.test.ts +226 -0
- data/templates/worker/wrangler.toml +63 -4
- metadata +154 -7
- data/lib/cloudflare/email/secure_message_id.rb +0 -89
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8b7e8e8e9c8f102cf640de5aa577092947f829853daea59463263b8729ede21
|
|
4
|
+
data.tar.gz: 7303add7cb750e309c338132e114ecd40340bf5e9ee39b6b03c3f28acd9887d1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77cbd0de1b51f621f834fa9493c31865cc0017e0f221885503ad6c891f783f39b3e0eaf07eaabb148a9e34c694bed9d8e4a0dfa27cd052e70e0d9e17164e9483
|
|
7
|
+
data.tar.gz: 3e3ee8aa24120e3b264efd7328b18dc3c48ab044656c0e15d0f73a13d2fd18e06247ab7392bc72aba472d37bee1b080a77113e492d4dcbe8c6945e2c5ceeb34a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,154 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.3.0 — 2026-09-13
|
|
4
|
+
|
|
5
|
+
See [upgrading from 0.2](docs/upgrading-0.3.md) before deploying the updated Worker.
|
|
6
|
+
|
|
7
|
+
- Add a standalone Deploy to Cloudflare template with R2/Queue provisioning,
|
|
8
|
+
secret prompts, scheduled recovery, and logs. CI checks runtime/configuration
|
|
9
|
+
synchronization with the gem's Worker and tests an isolated template copy.
|
|
10
|
+
|
|
11
|
+
- Make durable inbound delivery the Worker default, with explicit direct fallback: commit original mail and envelope context
|
|
12
|
+
to R2 before Worker acceptance, deliver queue pointers with fresh signatures,
|
|
13
|
+
and recover pending mail through a bounded scheduled sweep. Rails errors,
|
|
14
|
+
lost responses, enqueue failures and exhausted queue retries retain pending
|
|
15
|
+
mail. Provisioning, protected storage and monitoring remain explicit.
|
|
16
|
+
- Make missing Message-ID fallback deterministic across Rails hosts so replay
|
|
17
|
+
after a deployment does not create another inbound record. Original MIME and
|
|
18
|
+
parseable provider Message-IDs remain unchanged.
|
|
19
|
+
- Add optional authenticated Routing analytics delivery confirmation with
|
|
20
|
+
encrypted immutable receipts, strict single-envelope-recipient correlation,
|
|
21
|
+
replay and transactional callbacks. Sending acceptance remains unchanged;
|
|
22
|
+
missing or ambiguous evidence never authorizes a resend.
|
|
23
|
+
- Bound shared sending/queue HTTP responses by streamed bytes and a total
|
|
24
|
+
per-attempt deadline; disable implicit HTTP retries and sanitize transport
|
|
25
|
+
failures. Sending and queue acknowledgement ambiguity stays safe to replay
|
|
26
|
+
through durable receipts rather than resending accepted email.
|
|
27
|
+
- Document verified Routing destinations, separate analytics credentials and
|
|
28
|
+
explicit system-mail storage with optional SQLite tenancy.
|
|
29
|
+
|
|
30
|
+
- Add optional domain catch-all receiving on an existing active mailbox address,
|
|
31
|
+
with explicit verification evidence and a unique active catch-all constraint.
|
|
32
|
+
Exact registered addresses always win, including rejected inactive addresses;
|
|
33
|
+
unknown local parts retain their actual envelope recipient without new aliases.
|
|
34
|
+
Destination snapshots identify fallback, while sending stays exact-address only.
|
|
35
|
+
A separate generator upgrades existing mailbox schemas; catch-all is never
|
|
36
|
+
enabled automatically.
|
|
37
|
+
|
|
38
|
+
- Allow production Rails schema preloading to boot without a selected tenant.
|
|
39
|
+
Tenant model pool access still fails closed with
|
|
40
|
+
`Cloudflare::Email::ActiveRecord::TenantConnectionUnavailable`, an
|
|
41
|
+
`ActiveRecord::ConnectionNotEstablished` error retaining the original
|
|
42
|
+
`ConfigurationError` as its cause. No default tenant is selected.
|
|
43
|
+
|
|
44
|
+
- Add a reusable Worker `relayEmail` pipeline with host backend/header policies,
|
|
45
|
+
bounded raw reads, optional fail-open archive hooks, safe HTTP outcomes and
|
|
46
|
+
deadlines. `archiveEmail` writes raw bytes and envelope metadata to an optional
|
|
47
|
+
R2 bucket. Default and custom forwarding share the same HTTP transport.
|
|
48
|
+
- Keep provider authentication interpretation, archive keys, retry decisions and
|
|
49
|
+
fallback destinations with the host; existing default v2/v3 forwarding remains
|
|
50
|
+
compatible. Archive deadlines bound waiting but cannot cancel an in-flight write.
|
|
51
|
+
|
|
52
|
+
- Add `Mailboxes.with_recipient` for active-address resolution and immutable
|
|
53
|
+
destination context with host-owned persistence, without ActionMailbox.
|
|
54
|
+
- Yield the same destination from `Mailboxes.receive` so apps can link their
|
|
55
|
+
business records while retaining gem-managed raw email, metadata and membership
|
|
56
|
+
persistence. Host exceptions propagate instead of being reported as missing
|
|
57
|
+
mailbox records; existing no-argument receive blocks continue to work.
|
|
58
|
+
|
|
59
|
+
- Add a bounded, Rails-independent `Ingress.verify` API for existing ingestion
|
|
60
|
+
pipelines, with optional ActionMailbox persistence and tenant registry routing.
|
|
61
|
+
- Add opt-in v3 signatures for provider metadata supplied by custom Workers.
|
|
62
|
+
Metadata is authenticated transport evidence, not proof of sender authenticity.
|
|
63
|
+
Default Worker forwarding remains v2; upgrade Rails before enabling v3.
|
|
64
|
+
- Verify signatures against exact timestamp header bytes; decimal parsing is
|
|
65
|
+
used only for freshness. The bundled Worker's timestamp format is unchanged.
|
|
66
|
+
- Add GET-only `cloudflare:email:check_route` diagnostics for exact receiving-domain
|
|
67
|
+
DNS and Worker routing. Reports uncertainty without changing configuration or
|
|
68
|
+
claiming live delivery is verified.
|
|
69
|
+
|
|
70
|
+
- Add an opt-in server-rendered mailbox management engine with host authentication,
|
|
71
|
+
mailbox/domain scoping and per-action permissions. Manage mailboxes and aliases,
|
|
72
|
+
suspend/resume, preview plain-text messages and mark read/archive without
|
|
73
|
+
JavaScript or asset pipeline dependencies. The engine is never mounted by default.
|
|
74
|
+
|
|
75
|
+
- Fix managed domain and address activation in Rails apps with strict readonly
|
|
76
|
+
attributes enabled. Normalize immutable identities only when creating records;
|
|
77
|
+
later lifecycle updates retain the original domain and address.
|
|
78
|
+
|
|
79
|
+
## 0.2.0 — 2026-09-11
|
|
80
|
+
|
|
81
|
+
- Add optional managed mailboxes: domain directory, addresses/aliases, lifecycle,
|
|
82
|
+
incoming memberships, read/archive/purge APIs and raw-mail retention.
|
|
83
|
+
- Add explicit tenant connections, tenant-aware framework and mailbox jobs,
|
|
84
|
+
mailbox-authorized outbox sends, shared event intake/correlation and recovery.
|
|
85
|
+
Verify separate SQLite databases and actual `activerecord-tenanted` integration;
|
|
86
|
+
no new runtime dependency for plain Ruby consumers.
|
|
87
|
+
- Add a mailbox generator with separate shared/tenant migration paths and
|
|
88
|
+
user guides for mailbox management and database tenancy.
|
|
89
|
+
|
|
90
|
+
- Bound Rails and Worker inbound reads to 25 MiB by default; reject malformed or
|
|
91
|
+
stale signing headers before reading MIME. Require HTTPS remote endpoints.
|
|
92
|
+
- Restrict the development tunnel to email ingress and require a running guard;
|
|
93
|
+
redact client inspection, retry logs, and generated mailbox logging.
|
|
94
|
+
- Validate delivery-event schemas, preserve receipt evidence through ordinary
|
|
95
|
+
ActiveRecord updates, and tighten provider acceptance response handling.
|
|
96
|
+
- Remove Rails 7.1 support, update patched Rails/SQLite test floors, and audit
|
|
97
|
+
resolved Ruby dependencies in CI. See the dated security verification report.
|
|
98
|
+
|
|
99
|
+
- Add an optional durable Rails outbox: immutable MIME/envelope snapshots,
|
|
100
|
+
account-scoped operation keys, committed send claims, per-recipient acceptance
|
|
101
|
+
evidence, blocked uncertain retries, and audited subset reconciliation.
|
|
102
|
+
- Add `Outbox.prepare_mail`, identity-only `SendJob`, replay jobs/tasks and
|
|
103
|
+
`DeliveryEvents` to correlate provider events and update recipient lifecycle
|
|
104
|
+
state transactionally. Normalize receipt message IDs for indexed replay.
|
|
105
|
+
- Verify concurrent sends and event projection on PostgreSQL as well as SQLite;
|
|
106
|
+
include process termination, partial outcomes and post-acceptance persistence
|
|
107
|
+
failures. The inbox uses the shared ledger with preserved historical records.
|
|
108
|
+
|
|
109
|
+
- Authenticate SMTP envelope sender/recipient with the Worker's v2 HMAC format,
|
|
110
|
+
persist trusted metadata before routing, and expose `Envelope.for(inbound_email)`.
|
|
111
|
+
Preserve raw MIME and scope duplicate detection to the exact SMTP recipient.
|
|
112
|
+
Require v2 ingress; remove v1 compatibility and the unused signed Message-ID
|
|
113
|
+
helper. Coordinate Rails and Worker deployment; see docs/upgrading-0.2.md.
|
|
114
|
+
|
|
115
|
+
- Extract shared provider acceptance, delivery-event ordering, and Message-ID
|
|
116
|
+
normalization primitives from the inbox application.
|
|
117
|
+
- Add an opt-in ActiveRecord event inbox and `cloudflare:email:tracking` generator:
|
|
118
|
+
committed receipts before ACK, account/event uniqueness, payload-conflict
|
|
119
|
+
detection, unmatched replay, and transactional handlers with explicit outcomes.
|
|
120
|
+
|
|
121
|
+
- Verify actual local workerd-to-Rails delivery in CI. This exposed and fixed an
|
|
122
|
+
unsupported fetch redirect mode; use `manual` and reject the 3xx response.
|
|
123
|
+
Add reusable package/fresh-install/task verification and a dated evidence report.
|
|
124
|
+
|
|
125
|
+
- Add outbound delivery events through Cloudflare Queues HTTP pull, typed event
|
|
126
|
+
data, account/domain checks, per-message acknowledgement after handler success,
|
|
127
|
+
and a Rails `consume_events` task. Optional Rails receipts provide durable
|
|
128
|
+
deduplication; applications supply correlation and processing policy.
|
|
129
|
+
- Expose suppressed recipients and provider message IDs in responses/notifications;
|
|
130
|
+
support cc/bcc-only structured sends and HTTP-date Retry-After headers.
|
|
131
|
+
- Default to retrying only rate limits and pre-send connection failures. Ambiguous
|
|
132
|
+
network/5xx retries now require `retry_ambiguous: true` to accept duplication risk.
|
|
133
|
+
- Fix generated ENV credentials, send-only eager boot, duplicate ingress responses,
|
|
134
|
+
accidental generator deployment tasks, and development environment isolation.
|
|
135
|
+
- Require subdomain routing DNS preflight; refuse misleading subdomain catch-all
|
|
136
|
+
scope; use current apex DNS API and paginated rule lookup; surface setup failures.
|
|
137
|
+
- Update locked Worker tooling, require explicit Wrangler environments, bound
|
|
138
|
+
forwarding requests to 15 seconds, and reject redirects. Add scheduled CI,
|
|
139
|
+
dependency checks, actual Rails integration tests, and Ruby 4 / Rails 8.1 coverage.
|
|
140
|
+
- Require FROM for test sends; remove undocumented sending-domain discovery and
|
|
141
|
+
misleading diagnostic claims. Update DNS, SMTP, retry, and signed-ID guidance.
|
|
142
|
+
- Bound legacy signed Message-ID output to 900 bytes; reject empty decode secrets.
|
|
143
|
+
Live Cloudflare testing confirmed custom IDs are replaced; use provider IDs
|
|
144
|
+
for correlation, not sender authentication. See docs/upgrading-0.2.md.
|
|
145
|
+
- Accept plain JSON queue bodies returned by live Email Sending subscriptions,
|
|
146
|
+
retaining Base64 compatibility. Verify real delivery-event redelivery and ack.
|
|
147
|
+
|
|
148
|
+
## 0.1.0 — 2026-04-18
|
|
149
|
+
|
|
150
|
+
The notes below describe the original April implementation and its historical
|
|
151
|
+
verification. Current compatibility and security guidance is in the 0.2.0 docs.
|
|
4
152
|
|
|
5
153
|
- **`Cloudflare::Email::SecureMessageId`** — sign the outbound `Message-ID:`
|
|
6
154
|
with HMAC-SHA256. The recipient's reply naturally carries the signed id
|