Skip to main content

Module mail

Module mail 

Source
Expand description

Email: send with adapters (log, Resend, Cloudflare), receive from Email Routing.

Sending is Rails’ Action Mailer without the class: build an Email (several recipients, cc, bcc, headers, attachments and inline images) and hand it to send, or to deliver_later / deliver_in to send it from the background jobs queue (see jobs) so the request does not wait for the provider and a failed delivery is retried. Receiving is Action Mailbox: receive is the Worker’s email entry point and hands each message to the app as an InboundEmail. In ocre dev, dev_routes serves mailer previews, the emails sent, and a form that delivers test email to the mailbox.

use axum::extract::State;
use ocre::mail::{self, Email};
use ocre::{Ctx, Result};

async fn welcome(State(ctx): State<Ctx>) -> Result<&'static str> {
    let email = Email::new("ada@example.com", "Welcome", "Hello Ada,\n\nhttps://example.com/start\n")
        .html("<p>Hello Ada,</p><p><a href=\"https://example.com/start\">Start</a></p>");
    mail::send(&ctx, email).await?;
    Ok("sent")
}

§Configuration

The MAIL_ADAPTER Worker variable picks how mail leaves the Worker, with no guessing from which keys happen to be set, so a development machine holding a real API key never sends by accident:

  • log: prints the whole email (headers, text, HTML, attachments) to the Worker console between LOG_PREFIX lines, like Rails’ letter_opener, and in debug builds keeps the last 20 for /ocre/dev/mailers (see dev_routes). ocre new writes MAIL_ADAPTER=log to .dev.vars, which overrides the bindings.text variables in ocre dev. No configuration, no limits.
  • resend: POST https://api.resend.com/emails with the RESEND_API_KEY secret, MAIL_FROM on a domain verified in Resend. Free plan (September 2026): 100 emails a day, 3,000 a month, one domain; any recipient.
  • cloudflare: Cloudflare Email Service through the EMAIL_BINDING bindings.sendEmail() binding, MAIL_FROM on a domain onboarded to Email Service. Workers Free (September 2026) only delivers to verified destination addresses of the account; any recipient needs Workers Paid (3,000 a month included).

The sender is the email’s own from, else the MAIL_FROM variable, noreply@example.com or Name <noreply@example.com>. With MAIL_ADAPTER unset, sending fails with an Error::Internal naming the fix, so a production Worker never drops mail silently. For sign-up and password-reset mail on the free plan, use Resend.

Receiving uses Cloudflare Email Routing, free and unlimited on every plan. Every line Ocre logs about mail starts with LOG_PREFIX.

Structs§

Attachment
A file attached to an Email, or an inline image shown by its HTML.
Email
An outgoing email: recipients, a subject, a plain-text body, and optionally HTML, headers and attachments.
InboundEmail
An email that Cloudflare Email Routing delivered to the Worker, handed to the app’s mailbox.
Preview
A mailer action shown at /ocre/dev/mailers in ocre dev, rendered with sample data, like Rails’ mailer previews.

Constants§

APP_URL
Name of the Worker variable holding the app’s public address, https://shop.example.com, for links in emails.
EMAIL_BINDING
Name of the bindings.sendEmail() binding used when MAIL_ADAPTER = "cloudflare".
LOG_PREFIX
Prefix of every line Ocre logs about mail, e.g. in ocre dev output.
MAIL_ADAPTER
Name of the Worker variable that chooses the adapter: log, resend or cloudflare.
MAIL_FROM
Name of the Worker variable holding the sender address.
RESEND_API_KEY
Name of the Worker secret holding the Resend API key, used when MAIL_ADAPTER = "resend".

Functions§

address_with_name
Formats Name <address>, quoting the name when needed, like Rails’ email_address_with_name.
deliver_in
Checks email now and sends it from the jobs queue after delay, like Rails’ deliver_later(wait:).
deliver_later
Checks email now and sends it later from the background jobs queue, like Rails’ deliver_later.
dev_routes
Development pages for email, served by ocre dev only, like Rails’ /rails/mailers and Action Mailbox’s conductor.
receive
Runs the app’s mailbox handler for an email from Cloudflare Email Routing; the Worker’s email entry point.
send
Sends email now, from MAIL_FROM, with the adapter named by MAIL_ADAPTER.
url
An absolute URL for path on the app’s public address, the APP_URL variable (Rails’ _url helpers in mailers).