## What Custom emails / templates / drafts sent through Hexclave's **shared (development) email server** are no longer blocked with `RequiresCustomEmailServer`. They are now allowed, but their **subject and body are wrapped** at send time with a notice that this is a development email from Hexclave, so unexpected recipients know they can safely ignore it. The wrapper only applies to **project-defined content addressed to the project's own users**. Hexclave's own default-template emails (verification, password reset, magic link, etc.) and system notifications (credential-scanning alerts, internal feedback) are sent **verbatim**. ## How - **[send-email/route.tsx](apps/backend/src/app/api/latest/emails/send-email/route.tsx)** — removed the `RequiresCustomEmailServer` throw that blocked the shared server. - **[emails.tsx](apps/backend/src/lib/emails.tsx)** — added `wrapSharedDevEmail()` (prefixes the subject with `[Hexclave dev email]` and prepends a notice banner to HTML/text) and `isCustomEmailForSharedServer(recipient, createdWith, templateId)`. - **[email-queue-step.tsx](apps/backend/src/lib/email-queue-step.tsx)** — applies the wrapper at send time, gated on `emailConfig.type === "shared"` **and** the email being project-defined custom content. Applying it at send time reliably wraps both the subject (from `overrideSubject` or the template's `<Subject>`) and the rendered HTML. ### What counts as "wrap-eligible" `isCustomEmailForSharedServer` returns true only when **all** hold: 1. the email is addressed to one of the project's own users (recipient type is not `custom-emails`), **and** 2. it is a draft, a custom template, or raw HTML — i.e. **not** one of the built-in `DEFAULT_TEMPLATE_IDS`. Condition (1) exempts Hexclave's own system senders (credential-scanning revoke, internal feedback) which send raw HTML to bare addresses via `custom-emails` and would otherwise be mis-classified as project content. This was a bug caught in review — a leaked-API-key security alert to a shared-server customer would have been prefixed `[Hexclave dev email]` with a "you can safely ignore it" banner. The recipient type is already persisted on the outbox row, so no schema change was needed. ## Tests - **send-email.test.ts** — replaced the old "400 on shared config" test with two new tests: (a) a custom email on the shared server is delivered with the `[Hexclave dev email]` subject prefix + notice banner, and (b) a **default template** (`sign_in_invitation`) on the shared server is delivered **verbatim** (no prefix, no banner) — pinning the core safety contract. - **js/email.test.ts** — flipped the "throws RequiresCustomEmailServer" test to assert the send now resolves. Verified locally against a full stack: - ✅ `send-email.test.ts` — 18/18 - ✅ `js/email.test.ts` — 12/12 - ✅ `password/send-reset-code.test.ts` — passes (default templates on shared server stay unwrapped) ## Known limitations (intentional scope) - **Template CRUD still blocked on the shared server.** `internal/email-templates` routes still throw `RequiresCustomEmailServer`, so a shared-server project can send raw HTML / a default template via the API but cannot create or edit a *saved* custom template. Sending arbitrary HTML is unaffected; only the saved-template editor remains gated. - **A project can send a (project-edited) default template unwrapped** by calling `send-email` with a `template_id` equal to a built-in `DEFAULT_TEMPLATE_IDS` value. Low impact (requires a server key, limited upside), noted for awareness. ## Note: freestyle-mock fix included [freestyle-mock/Dockerfile](docker/dependencies/freestyle-mock/Dockerfile) now also accepts `/execute/v3/script`. The `freestyle` SDK bump in #1654 moved to `/v3`, but the mock only served `/v1`+`/v2`, so **all** local email rendering 404'd (pre-existing `dev` breakage, not from this feature). The v3 request/response is identical to v2. Happy to split this into its own PR if preferred. Out of scope: `emails/email-queue.test.ts` has 2 pre-existing snapshot failures (`margin:0` vs recorded `margin:0rem`, a `@react-email/components` version drift in the mock) — those tests use a custom email server, so this PR's shared-only code path never runs for them. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Email sending can now proceed when using a shared email server. * Development-style wrapping is applied to eligible shared-server custom email content, including HTML notice injection. * **Bug Fixes** * Removed the previous blocking “requires custom email server” behavior for shared-server configurations. * Default-template emails over the shared server are no longer wrapped. * **Tests** * Updated end-to-end and JS email tests to validate both wrapped custom-email behavior and unwrapped default-template behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|---|---|---|
| .agents/skills | ||
| .changeset | ||
| .claude | ||
| .cursor | ||
| .devcontainer | ||
| .github | ||
| .vscode | ||
| apps | ||
| configs | ||
| docker | ||
| docs | ||
| docs-mintlify | ||
| examples | ||
| packages | ||
| patches | ||
| scripts | ||
| sdks | ||
| skills/hexclave | ||
| .dockerignore | ||
| .gitignore | ||
| .gitmodules | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| skills-lock.json | ||
| turbo.json | ||
| vitest.shared.ts | ||
| vitest.workspace.ts | ||
Hexclave
The user infrastructure platform.
Hexclave handles everything around your users: authentication, teams, payments, emails, analytics, and much more. Start in minutes on the hosted cloud. Your data is always yours to export and self-host.
Get started
Setting up Hexclave is one prompt. Paste this into your coding agent of choice:
Read skill.hexclave.com and help me setup hexclave in this project
For AI agents
If you're an AI coding agent, use your web fetch tool or curl the skill documentation for up-to-date integration instructions:
curl -sSL "https://skill.hexclave.com?question=<your-question>&context=<your-context>"
What's included
Hexclave ships as a catalog of apps you switch on as your product needs them. Each one is built on the same user model, and new apps land regularly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Contributing
Hexclave is open source, and contributions are welcome. Read
CONTRIBUTING.md to get started, and say hello in
Discord before picking up anything large.
Found a security issue? Email security@hexclave.com.










