[Email Service] Retire /email-routing/ docs and clean up Email Service#31082
Open
ttoino wants to merge 12 commits into
Open
[Email Service] Retire /email-routing/ docs and clean up Email Service#31082ttoino wants to merge 12 commits into
ttoino wants to merge 12 commits into
Conversation
5293851 to
fa082d2
Compare
edcd2de to
75209a3
Compare
Review⏸️ Automatic reviews for this PR are paused. This PR has already received 2 automatic reviews. To run another review, a codeowner can comment
|
9bc23be to
21282b1
Compare
Carry forward technical details, procedures, and reference data from the older /email-routing/ documentation set that were dropped during the move to /email-service/. - Postmaster: ARC, inbound MX hostnames, sender rewriting, RBL/SMTP error format, full SPF breakdown, dual DKIM signature behaviour. - Workers API: message.reply() requirements (DMARC, once-per-event, 100 References limit) and the X-* header rule on forward(). - send_email binding variants: destination_address, allowed_destination_addresses, allowed_sender_addresses. - Platform limits: Email Routing inbound caps (200 rules, 200 addresses, 25 MiB inbound) and EXCEEDED_CPU guidance. - Domains: locked DNS records section, _dc-mx behaviour, leftover DKIM cleanup via the API. - New page: observability/audit-logs. - Misc: Activity log time-range filtering, SPF re-onboard fallback, Worker-rename route-binding warning, test-from-different-account tip.
Align WranglerConfig source blocks with the repo's predominant authoring convention (JSONC + // comments). The WranglerConfig component re-serializes between TOML and JSONC and strips comments during round-trip; JSONC sources let the default wrangler.jsonc tab display the inline comments where readers expect them. Also fix two malformed code fences in hard-bounce-handling.mdx and local-development/routing.mdx (stray 4-backtick closers that left the markdown structure broken).
Address a backlog of editorial TODOs and content inconsistencies discovered during a full review of the email-service docs. Content corrections - Fill stubbed Simple email example in api/send-emails/workers-api. - Fix Attachment field name contentType -> type (4 sites in email-attachments.mdx) to match the canonical interface. - Repair malformed 4-backtick fence and inconsistent indentation in the landing page's quick-start example. - Reconcile 5 MiB outbound limit between examples/email-attachments and platform/limits. - Convert in-handler auto-reply examples from env.EMAIL.send() to message.reply(), restoring DMARC and threading semantics. Queue consumer sites stay on env.EMAIL.send() with a note explaining why. Terminology and structure - Rename 'Custom addresses' -> 'Routing rules' and 'Catch-all address' -> 'Catch-all rule' throughout configuration/email-routing-addresses; preserve the #destination-addresses anchor used by inbound links. - Rewrite Domain management in configuration/domains: per-service removal flows; clarify locked-record semantics; correct that only Email Routing records can be unlocked, via the Email Routing settings page. - Update dashboard URLs to account/per-domain reality and replace 'Add destination/subdomain' button language with inline-form wording where the dashboard no longer exposes a button. - Restructure observability/logs status lists (Handled, Delivery failed, Error) and remove the inaccurate 'Email headers' section. - Add Email Routing datasets to observability/metrics-analytics. - Split Workers binding limits into Free/Paid columns and link to the canonical Workers platform limits page. Cleanups - Resolve 23 TODO markers across 6 files. - Remove stray 'type: example' frontmatter from 3 files. - Replace stale 'compatibility_date: "2024-01-01"' with $today. - Resolve sidebar.order collisions at the root (concepts=3, configuration=4, observability=8, reference=9, platform=10). - Drop the orphan partials/email-service/domain-setup partial. - Standardise Discord URL to https://discord.cloudflare.com. - Fix 'Suppressions lists' title typo and rename 'Observability & Logs' -> 'Observability and logs'. - Trailing slash on internal links; relative paths for /api/ references in REST API docs. - Remove unused component imports from 6 files.
Add 301 redirects from every old /email-routing/ URL to its /email-service/ equivalent (including section anchors where the content moved within a page) and a /email-routing/* catch-all in the Dynamic redirects section for anything not enumerated. Flatten the 4 pre-existing legacy redirect chains so each points directly at its final /email-service/ destination instead of chaining through /email-routing/. Within email-service, this commit also updates internal links and the MTA-STS image references that previously pointed at /email-routing/ paths. Move the MTA-STS images from assets/images/email-routing/ to assets/images/email-service/ so their new path matches the email-service product directory. Inbound links to /email-routing/ in files outside email-routing/ and email-service/ are left to a follow-up; the wildcard redirect keeps them functional in the meantime.
Remove the legacy /email-routing/ documentation tree. Every page is covered by a redirect to its /email-service/ replacement, added in the previous commit, and every inbound link across the repo has already been pointed at the new locations. - Delete all 26 pages under src/content/docs/email-routing/. - Delete the orphan partials email-routing-definition.mdx and enable-create-worker.mdx (no longer referenced after the pages are gone). Keep send-emails-workers-intro.mdx and types-bindings.mdx because they are still rendered by src/content/docs/workers/wrangler/configuration.mdx. - Delete src/content/directory/email-routing.yaml; the existing email-service.yaml entry covers the merged product.
Move the four historical Email Routing changelog entries into the email-service product folder so they continue to be indexed after the email-routing directory entry was retired. src/util/changelog.ts:getChangelogs() requires every changelog entry's containing folder to map to a valid src/content/directory/ entry. Deleting directory/email-routing.yaml in the previous commit broke that invariant for these files and made the page builder throw 'Unable to render Content because it is undefined' on any page that calls getChangelogs() (the index, per-product changelog pages, and per-post pages). - Move src/content/changelog/email-routing/*.mdx into src/content/changelog/email-service/ via git mv (4 files). The per-post URL pattern uses only the file slug, so existing /changelog/post/<slug>/ URLs continue to resolve. - Move src/assets/images/changelog/email-routing/subaddressing.png to src/assets/images/changelog/email-service/ to match. The referencing changelog entry already points at the new path. - Add redirects from /changelog/product/email-routing/ (and any paginated subpath) to /changelog/product/email-service/ so anyone with the old per-product changelog URL bookmarked lands on the merged product's changelog.
- Rename 'Rules per domain' -> 'Routing rules per domain' and drop 'custom address' from the row's note to align with the terminology refactor applied to the rest of the docs. - Correct the 200-address limit: it covers destination addresses, which are account-level (shared across domains), not custom addresses configured per domain. Rename the row and update its note accordingly. - Reword the paragraph below the table for the same terminology pass: 'custom address' -> 'email pattern'.
A final-pass audit caught a handful of malformed code blocks and admonitions left over from earlier prettier-induced reformatting. - index.mdx: close the wrangler.jsonc Tab's code fence with three backticks instead of four, so it renders as a fenced block instead of leaking raw backticks into the page. - get-started/send-emails.mdx: redent the <WranglerConfig> block in step 2 so it lines up with the surrounding ordered list. Prettier had spread the opener at 4 spaces and the content at 12 spaces, producing visible leading whitespace in the rendered jsonc. - get-started/route-emails.mdx: align the closing ::: of the 'Update configuration' caution block with its opener so it parses as an admonition rather than rendering the closing marker as text. - local-development/sending.mdx: add a txt language tag to the bare code fence containing the ArrayBuffer error message. - local-development/routing.mdx: drop the send_email binding from the wrangler config in the inbound-routing example. The worker only calls message.forward() and never uses env.EMAIL.send(), so the binding was misleading. - get-started/index.mdx: convert the empty stub page into a navigation page that renders <DirectoryListing /> so the Get started landing surfaces its children.
…rendering Final-pass audit touch-ups. - Resolve sidebar.order collisions within email-service subdirectories: configuration/email-routing-addresses (1->2) and subdomains (5->3), reference/troubleshooting (2->3) and faq (2->4). Remaining intra-directory collisions are with hideIndex'd index pages and have no effect on rendered order. - Replace stale 'go to **Email Routing**' phrasing with the full 'Compute > Email Service > Email Routing' dashboard path in five places across get-started/route-emails.mdx and configuration/email-routing-addresses.mdx. - Rename 'Create a forwarding rule' / 'Test your forwarding rule' headings in get-started/route-emails.mdx to 'routing rule' to match the dashboard's labelling. Update the redirect for /email-routing/get-started/test-email-routing/ so the anchor still resolves. - Update two 'custom address' references in reference/postmaster to 'email pattern' / 'routing rule email pattern' to match the terminology refactor applied earlier in this branch. - Fix the 2025-07-21 subaddressing changelog typo 'learn on to enable' -> 'learn how to enable'. - Remove unused DashButton and Render imports from concepts/deliverability. - Sentence-case headings: configuration/domains TabItem labels (MX Records, SPF Record, DKIM Record, DMARC Record, DNS Propagation, Record Conflicts) and bold subheadings (SPF/MX/ DKIM Conflicts) and the 'Existing SPF Records' aside title. Also examples/email-sending/email-attachments (PDF/Inline Images/File Uploads), reference/faq (Limits and Usage), and concepts/email-lifecycle (Stage Details:). - Promote 'More resources' from H3 to H2 on the landing page so it's a peer of 'Related products' rather than nested under it. - Convert the bold '**Next steps:**' paragraph at the end of api/route-emails/email-handler to a proper '## Next steps' H2. - Change ':::warning' to ':::caution' in configuration/email-routing-addresses. Starlight only supports note/tip/caution/danger asides; warning rendered as raw text.
Two build-blocking issues surfaced after the previous push.
1. The retired src/content/directory/email-routing.yaml left two
files with dangling 'products: email-routing' frontmatter
references that the docs schema rejects:
- analytics/graphql-api/tutorials/querying-email-routing.mdx
- workflows/examples/send-invoices.mdx
Update both to 'email-service'. Body links in
send-invoices.mdx still need migration and remain deferred in
.agents/EMAIL-SERVICE-FOLLOWUPS.md.
2. Three DashButton calls pointed at deeplinks that are not in
src/content/dash-routes/, so the DashButton component threw
'[DashButton] No route found for ...' at build time:
- /?to=/:account/email-service (used in domains.mdx and
metrics-analytics.mdx as the top-level Email Service entry)
- /?to=/:account/email-service/routing/destination-addresses
(used in email-routing-addresses.mdx and route-emails.mdx)
The bare /email-service URL is not a real dashboard
destination (Email Service is a sidebar grouping with Routing
and Sending children). Remove the two ambiguous DashButtons;
the surrounding prose already describes the navigation. Fall
back to the registered /email-service/routing parent URL for
the destination-addresses links since the prose already
directs users to the Destination Addresses tab from there.
Drop the now-unused DashButton import from
metrics-analytics.mdx.
Documentation issues addressed in a single pass after a comprehensive review:
Correctness fixes:
- Replace regex-based MIME parser example with postal-mime
- Replace O(n^2) stream reader pattern with Response().arrayBuffer()
- Replace btoa(String.fromCharCode(...)) with direct ArrayBuffer for
attachments (avoids RangeError on files >64 KB)
- Correct forward()/reply() return type from Promise<void> to
Promise<EmailSendResult> per workerd source
- Add ArrayBufferView to Attachment.content type
- Fix swapped REST API error codes (email.invalid / email.too_big)
- Add complete Email Routing dimensions table to metrics-analytics
(only sending was documented)
Content additions:
- Inbound (Email Routing) lifecycle section in concepts/email-lifecycle
with mermaid diagram and stage details
- Subdomain limit (50 per zone) on platform/limits and subdomains
- Email Sending audit log actions on observability/audit-logs
- MTA-STS testing-mode caution and DMARC cross-domain rua note
- Next steps sections on 9 pages that lacked them
- Intro paragraphs on 8 bare DirectoryListing index pages
Structure and consistency:
- Rename ambiguous 'Workers API' titles to 'Email handler' and 'Send
method' to disambiguate routing vs sending
- Reorganize mta-sts.mdx into two H2 sections with content properly
indented under list items
- Demote catch-all and subaddressing to H3 under Routing rules
- Renumber concepts sidebar order consecutively
- Replace REST API stubs to conform to Dev Platform norm: routing
REST API is now a navigation stub to /api/resources/email_routing/,
send-emails has 'Send REST API' (the one carve-out with full content
for the send endpoint) and a 'Configuration REST API' stub to
/api/resources/email_sending/
Style and convention:
- whitelist -> allowlist in headers reference
- company.com placeholders -> example.com (destinations) or
yourdomain.com (senders) per repo convention
- <ACCOUNT_ID> -> {account_id} in get-started
- Remove emoji from console.log strings and HTML email body examples
- Replace smart quotes with straight quotes
- ARC link http -> https
Cleanup:
- Remove placeholder 'Configuration details' section from postmaster
in favor of cross-links
- Remove 'Clean up leftover DKIM records' subsection (unclear scope)
- Remove stale 'Ranges last updated: December 13th, 2023' date stamp
- Replace vague daily-limits text with practical guidance
- Clarify pricing (per-account, monthly, bounces count, suppressed don't)
- Rename troubleshooting page from 'Troubleshoot SPF, DKIM and DMARC'
to plain 'Troubleshooting' to match actual scope
21282b1 to
60188ef
Compare
Sending to verified destination addresses is free on all plans, including when only Email Routing is configured, and never counts toward the monthly quota or daily sending limits. The docs previously implied the opposite: the pricing page stated Email Sending was Workers Paid only, and the limits page framed verified-recipient sending as a temporary testing affordance. - pricing: split the plan gating (arbitrary recipients require Workers Paid; verified destination addresses are free on all plans) and add a quota carve-out for verified sends - limits: rewrite the verified-addresses section with the correct gate (before onboarding a sending domain you can only send to verified addresses; after onboarding you can send to anyone immediately) and document that verified sends are free, quota- and limit-exempt, and must originate from your routing domains - email-routing-addresses: note that destination addresses can be used as free send targets via the REST API or Workers binding - index: surface the free verified-recipient send path on the landing page Standardize terminology on 'verified destination addresses'.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR retires the standalone
/email-routing/documentation tree and folds it into Email Service, the merged product covering both inbound (Email Routing) and outbound (Email Sending) email on the developer platform. It also resolves a long-standing backlog of inconsistencies, stale content, and structural issues in the Email Service docs that built up during the migration.Documentation consolidation
/email-routing/page tree (26 pages, two orphan partials, and the duplicate directory entry).send_emailbinding variants, the Email Routing platform limits, locked-DNS records mechanics, and a new audit logs page./email-routing/...URL to its/email-service/...equivalent (with section anchors where content moved within a page) and a catch-all for anything not enumerated. Flatten four pre-existing legacy redirect chains.email-service/docs, partials, and changelog entries. External-file inbound links continue to resolve via the redirects; they are tracked for a follow-up.email-serviceproduct folder, and add redirects so the old per-product changelog URL still resolves.Content corrections
Attachmentfield-name mismatch (contentType→type) that would have made the example code fail against the canonical Workers binding interface.env.EMAIL.send()tomessage.reply()so DMARC alignment and threading semantics are preserved. Queue-consumer sites stay onenv.EMAIL.send()because the originalEmailMessageis no longer in scope there.:::warningto:::caution(Starlight does not supportwarning).Terminology and dashboard alignment
#destination-addressesanchor used by inbound links).Structure and consistency
observability/logsstatus lists (Handled,Delivery failed,Error) and remove the inaccurate "Email headers" section.observability/metrics-analytics.WranglerConfigsource blocks from TOML to JSONC so inline//comments survive the component's TOML↔JSONC round-trip on the defaultwrangler.jsonctab. Fix two malformed code fences along the way.configuration/andreference/.configuration/domains.mdxand elsewhere, add trailing slashes on internal links, switch fully-qualifiedhttps://developers.cloudflare.com/api/...links to relative/api/..., remove unused component imports.Closes EMAIL-1832
Documentation checklist