Lettermint

Send transactional emails via Lettermint from Convex with durable queuing, batching, rate limiting, webhook verification, and delivery event tracking.

Installation

npm install convex-lettermint

About Lettermint

convex-lettermint integrates the Lettermint transactional email service with Convex, providing a durable email queue backed by Convex workpools. Emails are batched to Lettermint's `/send/batch` endpoint with idempotency keys derived from internal Convex email IDs, and delivery events are tracked via verified HMAC-signed webhooks. The component handles rate limiting, retry backoff, and status tracking out of the box.

Benefits

Use cases

how to send transactional email from Convex backend

The convex-lettermint component provides a Lettermint class you instantiate with your component reference and options. Call lettermint.sendEmail(ctx, { from, to, subject, html }) inside any Convex mutation or action and the component queues the email for durable batched delivery to the Lettermint API.

how to handle email delivery webhooks in Convex

Mount an HTTP route in convex/http.ts and pass the request to lettermint.handleLettermintEventWebhook(ctx, req). The component verifies the X-Lettermint-Signature HMAC-SHA256 signature, rejects stale or invalid requests, and fires a registered onEmailEvent mutation with the email ID and event type.

retry failed email sends in Convex with backoff

convex-lettermint uses Convex workpools internally to retry failed Lettermint API calls. The initialBackoffMs option sets the starting backoff (default 30 seconds) and retryAttempts sets the maximum number of attempts (default 5), so transient API errors are handled without any additional application code.

send email with attachments from Convex action

Use lettermint.sendEmailManually(ctx, emailMetadata, callback) in a Convex Node action. The callback receives a tracked emailId to use as the Idempotency-Key and you call the Lettermint API directly with the full request body including attachments. The component records the send attempt and tracks status through webhooks.

Frequently asked questions

Does convex-lettermint support email templates?

convex-lettermint does not support Lettermint template IDs because the Lettermint Sending API schema used by the component does not include a template field. You should generate HTML before calling sendEmail, either with plain string interpolation or with React Email rendered inside a Convex Node action.

How do I track whether an email was opened or clicked?

convex-lettermint returns a branded EmailId from sendEmail. Call lettermint.status(ctx, emailId) to read the current delivery state including the bounced, failed, complained, opened, and clicked boolean fields. Status is updated when Lettermint webhook events arrive and are processed by the component.

How do I cancel a queued email before it is sent?

Call lettermint.cancelEmail(ctx, emailId) with the EmailId returned from sendEmail. If the email has already been submitted to the Lettermint API it cannot be cancelled. Cancellation only works while the email is still in the component's internal queue.

What environment variables does convex-lettermint require?

convex-lettermint reads LETTERMINT_PROJECT_TOKEN for the Lettermint Project API token and LETTERMINT_WEBHOOK_SECRET for webhook signature verification. Both values can alternatively be supplied directly via the projectToken and webhookSecret fields in the LettermintOptions constructor argument, which avoids reading from environment variables.

How do I clean up old email records stored by the component?

convex-lettermint exposes cleanupOldEmails and cleanupAbandonedEmails functions on the component. Schedule them from a Convex cron job or run them from the Convex dashboard, passing an olderThan millisecond threshold. For example, passing { olderThan: 604800000 } removes emails finalized more than one week ago.

Links