Skip to content

Conversation

@penalosa
Copy link
Contributor

@penalosa penalosa commented Jan 15, 2026

Implements support for the simplified MessageBuilder interface in Miniflare's Email Sending API binding. This provides a developer-friendly alternative to manually constructing MIME messages with the EmailMessage API.

Key changes:

  • Add TypeScript types for MessageBuilder API (types.ts)
  • Implement send() overload accepting MessageBuilder alongside EmailMessage
  • Store email content (text, HTML, attachments) to viewable temp files
  • Extract common storeTempFile() helper to reduce duplication
  • Add comprehensive test coverage (12 new tests)

In local mode, content is saved to files that developers can open in their editor/browser for inspection, with file paths logged to the console.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: pre-release

A picture of a cute animal (not mandatory, but encouraged)

… mode

Implements support for the simplified MessageBuilder interface in Miniflare's
Email Sending API binding. This provides a developer-friendly alternative to
manually constructing MIME messages with the EmailMessage API.

Key changes:
- Add TypeScript types for MessageBuilder API (types.ts)
- Implement send() overload accepting MessageBuilder alongside EmailMessage
- Store email content (text, HTML, attachments) to viewable temp files
- Extract common storeTempFile() helper to reduce duplication
- Add comprehensive test coverage (12 new tests)

In local mode, content is saved to files that developers can open in their
editor/browser for inspection, with file paths logged to the console.
@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

🦋 Changeset detected

Latest commit: 7b8629b

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@penalosa penalosa changed the title [miniflare] Add MessageBuilder support for Email Sending API in local… Add MessageBuilder support for Email Sending API in local mode Jan 15, 2026
@github-project-automation github-project-automation bot moved this to Untriaged in workers-sdk Jan 15, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 15, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@11942

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@11942

miniflare

npm i https://pkg.pr.new/miniflare@11942

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@11942

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@11942

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@11942

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@11942

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@11942

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@11942

wrangler

npm i https://pkg.pr.new/wrangler@11942

commit: 7b8629b


Add support for Email Sending API's MessageBuilder interface in local mode

Miniflare now supports the simplified MessageBuilder interface for sending emails, alongside the existing EmailMessage (raw MIME) support. This matches the API available in production Workers.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
Miniflare now supports the simplified MessageBuilder interface for sending emails, alongside the existing EmailMessage (raw MIME) support. This matches the API available in production Workers.
Miniflare now supports the simplified MessageBuilder interface for sending emails, alongside the existing `EmailMessage` support.

await env.EMAIL.send({
from: { name: "Alice", email: "[email protected]" },
to: ["[email protected]"],
subject: "Hello from Miniflare",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
subject: "Hello from Miniflare",
subject: "Hello",

});
```

In local mode, email content (text, HTML, attachments) is stored to temporary files that you can open in your editor or browser for inspection. File paths are logged to the console when emails are sent.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
In local mode, email content (text, HTML, attachments) is stored to temporary files that you can open in your editor or browser for inspection. File paths are logged to the console when emails are sent.

} else if (content instanceof ArrayBuffer) {
body = new Uint8Array(content);
} else {
// ArrayBufferView
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
// ArrayBufferView

- Simplify changeset description
- Shorten example subject to 'Hello'
- Remove trailing newline in changeset
- Remove extra blank line in send_email.worker.ts
Adds comprehensive manual testing examples for the MessageBuilder API:
- /send-simple: Basic text-only email
- /send-html: Email with text and HTML content
- /send-attachment: Single text attachment
- /send-multi-attachment: Multiple attachment types (text, JSON, binary)
- /send-complex: Multiple recipients (to/cc/bcc)
- /test-bindings: Test all three binding types

Also includes:
- README with complete usage instructions
- Documentation of expected console output
- Notes about type assertions (types not yet in @cloudflare/workers-types)

Tested locally - all routes work correctly.
The validateMessageBuilder function was passing EmailAddress objects
(with { name, email } structure) directly to validateRecipients, which
expected strings. This caused the error 'email to [object Object] not allowed'.

Fix: Extract email addresses from EmailAddress objects before validation
using the existing extractEmailAddress helper.

Tested with fixture routes that use EmailAddress objects:
- /send-simple (named sender)
- /send-complex (multiple recipients with names)

All tests pass.
The MessageBuilder snapshot test was failing on Windows because the regex
only matched Unix-style paths (/...). Updated the regex to also match
Windows paths (C:\...) while still normalizing both to the same format.

Regex now matches:
- Unix: /var/folders/.../email-text/uuid.txt
- Windows: C:\Users\...\email-text\uuid.txt

Both normalize to: /email-text/[FILE].txt
The proxy server previously only handled EmailMessage objects by
reconstructing them from the serialized 'EmailMessage::raw' property.
This fix adds detection for MessageBuilder objects and passes them
through directly since they're already plain serializable objects.

Changes:
- Check if the argument has 'EmailMessage::raw' property to distinguish
  EmailMessage from MessageBuilder
- EmailMessage: Reconstruct with EmailMessage constructor (existing behavior)
- MessageBuilder: Pass through directly as plain object (new behavior)

Both APIs now work correctly in remote mode via wrangler dev --remote.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

1 participant