---
name: bijection-cloudflare-email
description: "Evaluate and integrate the Cloudflare Email component with Bijection."
---

# Cloudflare Email

Durable email sending with Cloudflare Email Service for Bijection.

- Package: @bijectionhq/cloudflare-email
- Category: Messaging
- Status: Preview
- License: MIT
- Bijection source (repository access required): https://github.com/bijectionhq/cloudflare-email/tree/919f51e01fee9090809ba9991f1fd4153cd2fddd
- Upstream: https://github.com/adamtrip-solutions/convex-cloudflare-email/tree/0f73fec45c1e0fe18ca8530a6727631240658975
- Documentation: https://docs.bijection.com/components/using
- Directory: https://bijection.com/components/cloudflare-email

## Get the source

Bijection repository access is required. Request access at https://bijection.com/contact.

```sh
git clone https://github.com/bijectionhq/cloudflare-email.git
cd cloudflare-email
git checkout 919f51e01fee9090809ba9991f1fd4153cd2fddd
```

## Before using this component

Read the package README at the recorded revision for setup, dependencies, and API examples. Upstream documentation describes the original package and may differ from the Bijection adaptation. This is a source candidate for evaluation. Catalog inclusion does not establish npm availability or runtime qualification. Check compatibility with your SDK and deployment before adoption. External providers run their own compute.

## Integration workflow

1. Read the source README and package manifest at the recorded revision.
2. Confirm the required SDK, dependency availability, and runtime compatibility.
3. Follow the component's documented setup and configuration. Never invent an npm install command from a catalog package name.
4. Keep credentials in the project's existing secret store.
5. Follow the project's execution rules for verification and report what was actually checked.

## Original upstream skill

The following guidance describes convex-cloudflare-email. Its installation commands and APIs refer to the upstream package. Evaluate compatibility with the Bijection source separately.


> Agents: read this skill fully before writing code that uses Cloudflare Email Sender. Follow the installation and configuration steps exactly.

# Cloudflare Email Sender

## Instructions

Use Cloudflare Email Sender to send transactional email via cloudflare's rest api from convex mutations with queuing, deduplication, status tracking, and bounded retries. This Convex component integrates directly with your backend.

### Installation

```bash
npm install convex-cloudflare-email
```

Current npm version: `convex-cloudflare-email@0.1.0-beta.0`

### Capabilities

- Enqueue emails inside Convex mutations so sends roll back automatically if the parent transaction fails
- Track per-email status through pending, sending, sent, failed, and unknown states with attempt counts and timestamps
- Deduplicate sends using idempotency keys scoped to the component, preventing duplicate jobs from repeated mutations
- Rotate Cloudflare API credentials without requeuing jobs because credentials are read at attempt time, not enqueue time

## Examples

### how to send email from a Convex mutation without side effects on rollback

The convex-cloudflare-email component lets you call email.sendEmail() inside a Convex mutation. The enqueue is part of the mutation's transaction, so if the transaction aborts the email is never queued. This avoids the common problem of sending an email for a write that never committed.

### how to add retry logic to Cloudflare email sending in Convex

The component uses convex-dev/workpool internally and retries HTTP 429 responses with exponential backoff, honoring Retry-After headers. You configure maxAttempts (1 to 10) and initialBackoffMs on the CloudflareEmail instance. Network failures and 5xx responses are marked unknown rather than retried blindly, because Cloudflare's send API has no documented idempotency guarantee.

### how to deduplicate transactional emails in Convex

Pass an idempotencyKey string to email.sendEmail(). The convex-cloudflare-email component rejects a second enqueue with the same key if a job for that key already exists in the component. After a completed record is deleted by cleanup(), the key becomes available again, so retention period should match the deduplication window your application requires.

### how to track email delivery status in a Convex backend

Call email.getStatus(ctx, id) from any query or action context. It returns the status string, attempt count, timestamps, and a result object containing delivered, queued, permanentBounces, and suppressedRecipients arrays when the send succeeded. The component does not consume Cloudflare Event Subscriptions, so delivery events beyond the initial API response are not reflected automatically.

## When NOT to use

- When a simpler built-in solution exists for your specific use case
- If you are not using Convex as your backend
- When the functionality provided by Cloudflare Email Sender is not needed

## Troubleshooting

**Does convex-cloudflare-email require a Cloudflare Worker to send email?**

No. The convex-cloudflare-email component calls Cloudflare's Email Sending REST API directly from Convex actions. You need a Cloudflare account with an onboarded sending domain and an API token scoped to Email Sending: Edit, but no Worker deployment is required.

**What happens if the HTTP request to Cloudflare times out or returns a 5xx error?**

The convex-cloudflare-email component marks the email unknown rather than failed. Unknown status means an attempt may have reached Cloudflare but its result is uncertain. A watchdog marks abandoned in-progress attempts unknown after 15 minutes. You can call email.retryEmail() on an unknown email after checking Cloudflare logs, but you must pass acknowledgeDuplicateRisk: true because a duplicate send could occur.

**How do I test email sending locally without real Cloudflare credentials?**

The CloudflareEmail instance defaults to testMode: true. In test mode, sendEmail() completes with a test status without making any HTTP request or requiring CLOUDFLARE_ACCOUNT_ID or CLOUDFLARE_API_TOKEN. For unit tests in a consuming app, import register from convex-cloudflare-email/test and call register(t) after creating a convexTest instance.

**Can I cancel an email after calling sendEmail()?**

Yes, call email.cancelEmail(ctx, id) from a mutation or action while the email is in pending status. Once a worker has claimed the job and the status moves to sending, cancellation is no longer possible. The method returns a boolean indicating whether cancellation succeeded.

**How does convex-cloudflare-email handle credential rotation?**

Credentials are read from Convex environment variables when each send attempt runs, not when the email is enqueued. Updating CLOUDFLARE_ACCOUNT_ID or CLOUDFLARE_API_TOKEN with npx convex env set takes effect for all subsequent attempts, including retries of already-queued emails. No requeuing is needed after a credential rotation.

## Resources

- [npm package](https://www.npmjs.com/package/convex-cloudflare-email)
- [GitHub repository](https://github.com/adamtrip-solutions/convex-cloudflare-email)
- [Live demo](https://cloudflare-email-demo.adamtrip.pt/)
- [Convex Components Directory](https://www.convex.dev/components/convex-cloudflare-email)
- [Convex documentation](https://docs.convex.dev)