Skip to content

feat: add Cloudflare Email support for Better Auth#57

Open
FRFlo wants to merge 14 commits into
zpg6:mainfrom
FRFlo:email
Open

feat: add Cloudflare Email support for Better Auth#57
FRFlo wants to merge 14 commits into
zpg6:mainfrom
FRFlo:email

Conversation

@FRFlo

@FRFlo FRFlo commented Jun 16, 2026

Copy link
Copy Markdown

Summary

This PR implements the Cloudflare Email roadmap item by adding a typed Email Sending integration for Better Auth transactional emails.

What changed

  • Added Cloudflare Email sender helpers and types:

    • createEmailSender
    • createEmailOptions
    • CloudflareEmailConfig
  • Wired withCloudflare to fill Better Auth email callbacks when email is configured:

    • email verification
    • password reset
  • Added CLI generation support for Email:

    • --email
    • --email-binding
    • --email-from
  • Generated the correct Wrangler Email Sending TOML shape:

    [[send_email]]
    name = "EMAIL"
  • Updated Hono and OpenNext examples with Email bindings, env typings, and auth config.

  • Updated README, CLI README, configuration reference, and package metadata.

  • Added Bun test coverage for Email helpers and CLI generation.

  • Fixed CLI TypeScript validation to prefer the local TypeScript compiler.

Validation

  • Root typecheck passed: npm run typecheck
  • CLI typecheck passed: npm run typecheck in cli
  • Targeted CLI Bun tests passed: 89 pass, 0 fail
  • Wrangler TOML Email binding shape was validated against generated/example configs.

Notes

  • The sender address configured through BETTER_AUTH_EMAIL_FROM must belong to a domain configured in Cloudflare Email Service.
  • Existing user-provided Better Auth email callbacks are preserved; the Cloudflare defaults are only added when callbacks are missing.

@pkg-pr-new

pkg-pr-new Bot commented Jun 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/better-auth-cloudflare@57

commit: 2497d6d

@zpg6

zpg6 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Open in StackBlitz

npm i https://pkg.pr.new/better-auth-cloudflare@57

commit: 87544fb

Hi @FRFlo - great contribution thanks!! Would you be willing to try the built version see if it still works well for you? Any test report, artifacts, etc you can attach is greatly appreciated

@zpg6 zpg6 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, this is clean. And thanks for adding to CLI capabilities too. A few things I'd want changed before merge:

  • Configuring email sets emailAndPassword.enabled: true even for users who never set emailAndPassword at all. Someone on OAuth/magic-link/OTP would get password auth turned on without asking.

  • opennextjs example passes email unconditionally, while Hono only sets it when the binding exists (env?.EMAIL). Could we guard it the same way Hono does so the two examples behave consistently?

  • Default templates could use a "if you didn't request this, ignore this email". better-auth's demo has this.

  • The "domain must be onboarded in Cloudflare Email Service" note is in the CLI readme/docs but there's no actual link to CF's docs, and nothing in the main README. Maybe add something..

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class Cloudflare Email Sending support to better-auth-cloudflare, including typed helpers to send transactional emails and CLI + example updates to generate/configure the required Wrangler bindings.

Changes:

  • Added CloudflareEmailConfig types plus createEmailSender / createEmailOptions, and wired withCloudflare to auto-fill Better Auth email callbacks when configured.
  • Extended the CLI to generate/update Wrangler + env typings + auth scaffolding for Email Sending (flags, templates, validation), with added Bun test coverage.
  • Updated documentation and examples to include Email Sending bindings, env vars, and Better Auth configuration.

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/types.ts Adds Cloudflare Email config/types to public API surface.
src/index.ts Wires email options into withCloudflare and re-exports email helpers.
src/email.ts Implements email sender + Better Auth option wiring helpers.
README.md Documents Email support and updates example configuration snippets.
package.json Updates package description/keywords to include Email.
examples/opennextjs/wrangler.toml Adds [[send_email]] binding and BETTER_AUTH_EMAIL_FROM.
examples/opennextjs/src/auth/index.ts Adds Email config + Better Auth email options in example.
examples/opennextjs/env.d.ts Adds SendEmail binding + BETTER_AUTH_EMAIL_FROM typing.
examples/hono/wrangler.toml Adds [[send_email]] binding and BETTER_AUTH_EMAIL_FROM.
examples/hono/src/env.d.ts Adds SendEmail binding + BETTER_AUTH_EMAIL_FROM typing.
examples/hono/src/auth/index.ts Adds optional Email wiring + email verification config.
docs/configuration.md Documents Email option and exported helpers; updates override behavior table.
cli/tests/wrangler-generator.test.ts Adds tests for Email Sending TOML generation.
cli/tests/non-interactive-args.test.ts Adds tests for new --email* flags and binding validation.
cli/tests/env-d-generator.test.ts Adds tests for env typing generation with Email enabled.
cli/tests/email-helper.test.ts Adds Bun tests for email helpers and default templates.
cli/tests/auth-generator.test.ts Adds tests ensuring generated auth code includes Email wiring.
cli/src/lib/wrangler-generator.ts Generates [[send_email]] + BETTER_AUTH_EMAIL_FROM in TOML output.
cli/src/lib/typescript-validator.ts Prefers local TypeScript compiler when validating generated projects.
cli/src/lib/env-d-generator.ts Generates env typings for Email binding + sender address var.
cli/src/lib/auth-generator.ts Adds Email wiring to generated auth configuration for templates.
cli/src/index.ts Adds interactive + non-interactive CLI support for Email flags/inputs.
cli/README.md Documents Email flags, behavior, and usage examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/email.ts Outdated
Comment on lines +71 to +90
const sender = createEmailSender(email);
const emailVerification: EmailVerificationOptions = { ...(options.emailVerification ?? {}) };
const emailAndPassword: EmailAndPasswordOptions = { enabled: true, ...(options.emailAndPassword ?? {}) };

if (email.sendVerificationEmail !== false && !emailVerification.sendVerificationEmail) {
emailVerification.sendVerificationEmail = async ({ user, url, token }, request) => {
const content = await (email.templates?.verification ?? defaultVerificationTemplate)({
user,
url,
token,
request,
});
await sender({
to: user.email,
...content,
});
};
}

if (email.sendResetPassword !== false && !emailAndPassword.sendResetPassword) {
Comment thread docs/configuration.md Outdated
| `advanced` | Merges your `authOptions.advanced` with IP detection headers when `autoDetectIpAddress` is enabled. |
| `session` | Merges your `authOptions.session`, forcing `storeSessionInDatabase: true` when `geolocationTracking` is enabled — even if you explicitly set it to `false`. |
| `emailVerification` | Adds a Cloudflare Email `sendVerificationEmail` callback when `email` is configured and no custom callback exists. |
| `emailAndPassword` | Adds a Cloudflare Email `sendResetPassword` callback when `email` is configured and no custom callback exists. |
Comment thread cli/src/lib/wrangler-generator.ts Outdated
@FRFlo

FRFlo commented Jun 16, 2026

Copy link
Copy Markdown
Author

Open in StackBlitz

npm i https://pkg.pr.new/better-auth-cloudflare@57

commit: 87544fb

Hi @FRFlo - great contribution thanks!! Would you be willing to try the built version see if it still works well for you? Any test report, artifacts, etc you can attach is greatly appreciated

Hi !
I've not really experienced OpenNextJS so i don't really know how to produce reports or artifacts for you. I'm using this package in prod on sveltekit projects since a while and it works great (and i can remember talking about a svelte example a long time ago), i'm planning to ship soon a sveltekit example which can help giving you some reports and artifacts.

@FRFlo

FRFlo commented Jun 16, 2026

Copy link
Copy Markdown
Author

Nice work, this is clean. And thanks for adding to CLI capabilities too. A few things I'd want changed before merge:

* Configuring `email` sets `emailAndPassword.enabled: true` even for users who never set `emailAndPassword` at all. Someone on OAuth/magic-link/OTP would get password auth turned on without asking.

* opennextjs example passes `email` unconditionally, while Hono only sets it when the binding exists (`env?.EMAIL`). Could we guard it the same way Hono does so the two examples behave consistently?

* Default templates could use a "if you didn't request this, ignore this email". better-auth's demo has this.

* The "domain must be onboarded in Cloudflare Email Service" note is in the CLI readme/docs but there's no actual link to CF's docs, and nothing in the main README. Maybe add something..

Yes, ofc ! Anything else ? I just saw copilot introduced some comments, just reviewing them and then i work on it !

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@zpg6

zpg6 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Nice work, this is clean. And thanks for adding to CLI capabilities too. A few things I'd want changed before merge:

* Configuring ``email`` sets ``emailAndPassword.enabled: true`` even for users who never set ``emailAndPassword`` at all. Someone on OAuth/magic-link/OTP would get password auth turned on without asking.

* opennextjs example passes ``email`` unconditionally, while Hono only sets it when the binding exists (``env?.EMAIL``). Could we guard it the same way Hono does so the two examples behave consistently?

* Default templates could use a "if you didn't request this, ignore this email". better-auth's demo has this.

* The "domain must be onboarded in Cloudflare Email Service" note is in the CLI readme/docs but there's no actual link to CF's docs, and nothing in the main README. Maybe add something..

Yes, ofc ! Anything else ? I just saw copilot introduced some comments, just reviewing them and then i work on it !

I don't think copilot recommended anything I didn't already cover. make sure you update all relevant docs. you can resolve copilots review and mine once you fix. no worries about opennextjs artifacts if you implement the same way as you do hono (but still want to see something)

@FRFlo

FRFlo commented Jun 16, 2026

Copy link
Copy Markdown
Author

Okay, just implemented everything per your request, let me know if you want anything else changed

@FRFlo FRFlo requested a review from zpg6 June 16, 2026 15:46
@zpg6

zpg6 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Okay, just implemented everything per your request, let me know if you want anything else changed

emailAndPassword change, OpenNext guard, and doc links look good

opennextjs template generates emailVerification: { sendOnSignUp: true } but no emailAndPassword, so a generated Next.js project never wires sendResetPassword — reset emails silently won't send. Hono works because it has emailAndPassword: { enabled: true }. Should match I think

docs/configuration.md still says sendResetPassword is added "when email is configured", but it now only wires when emailAndPassword is already set

Don't see the "if you didn't request this, ignore this email" line if you agreed with me that was a fair default.

@FRFlo

FRFlo commented Jun 23, 2026

Copy link
Copy Markdown
Author

Hi @zpg6 , can you review the pull request for merge ?

@FRFlo

FRFlo commented Jun 28, 2026

Copy link
Copy Markdown
Author

@zpg6 any updates ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants