Cloudflare announced on April 16, 2026 that Email Service is in public beta with a clear focus on agent workflows.

If you build inbox automations, support copilots, or async back-office agents, this release matters because the send and reply loop can stay inside Cloudflare Workers.

What changed in the beta

Based on Cloudflare’s announcement, the practical upgrades are:

  1. Native email sending from Workers so your app can send without bolting on another provider API for the basic flow.
  2. Email MCP + Wrangler tooling so coding agents and developer workflows can configure and trigger email tasks faster.
  3. Async-friendly agent patterns so a Worker can process in the background and reply when work is done.

That combination is especially useful for:

  • support follow-ups after async investigation,
  • invoice or export-ready notifications,
  • approval and human-in-the-loop email steps,
  • long-running agent jobs that need a final threaded reply.

Temp API lib that checks UnwrapEmail before send

Instead of maintaining a temporary regex and disposable-domain list in your Worker, you can call UnwrapEmail first and only send when the address is safe.

type UnwrapEmailValidationResponse = {
  safe_to_send?: boolean
  is_disposable?: boolean
  has_valid_mx_records?: boolean
  reason?: string
}

export type TempEmailPreflightInput = {
  email: string
  apiKey: string
  timeoutMs?: number
}

export type TempEmailPreflightResult =
  { ok: true } | { ok: false; reason: string }

export const runTempEmailPreflight = async (
  input: TempEmailPreflightInput,
): Promise<TempEmailPreflightResult> => {
  const controller = new AbortController()
  const timeout = setTimeout(() => {
    controller.abort()
  }, input.timeoutMs ?? 4_000)

  try {
    const response = await fetch(
      `https://api.unwrap.email/v1/emails/validate?email=${encodeURIComponent(input.email)}&validate_domain=1`,
      {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${input.apiKey}`,
        },
        signal: controller.signal,
      },
    )

    if (!response.ok) {
      return {
        ok: false,
        reason: `UnwrapEmail request failed with status ${response.status}`,
      }
    }

    const validation = (await response.json()) as UnwrapEmailValidationResponse

    if (!validation.safe_to_send) {
      return {
        ok: false,
        reason: validation.reason ?? 'Address is not safe to send.',
      }
    }

    if (validation.is_disposable) {
      return {
        ok: false,
        reason: 'Disposable inboxes are blocked for transactional sends.',
      }
    }

    if (!validation.has_valid_mx_records) {
      return {
        ok: false,
        reason: 'Domain MX records are invalid for delivery.',
      }
    }

    return { ok: true }
  } catch (error) {
    const reason =
      error instanceof Error ? error.message : 'Unknown validation failure.'

    return {
      ok: false,
      reason: `UnwrapEmail request failed: ${reason}`,
    }
  } finally {
    clearTimeout(timeout)
  }
}

Send wrapper for Cloudflare Worker email binding

This wrapper enforces the UnwrapEmail preflight check before any Worker send operation.

import { runTempEmailPreflight } from './temp-email-preflight'

type WorkerEmailBinding = Pick<SendEmail, 'send'>

type SendTransactionalEmailInput = {
  to: string
  from: string
  subject: string
  text: string
  unwrapEmailApiKey: string
}

export const sendTransactionalEmail = async (
  email: WorkerEmailBinding,
  input: SendTransactionalEmailInput,
): Promise<void> => {
  const preflight = await runTempEmailPreflight({
    email: input.to,
    apiKey: input.unwrapEmailApiKey,
  })

  if (!preflight.ok) {
    throw new Error(
      `Email blocked by UnwrapEmail preflight: ${preflight.reason}`,
    )
  }

  await email.send({
    to: input.to,
    from: input.from,
    subject: input.subject,
    text: input.text,
  })
}

Next hardening steps

  • Add retry + circuit-breaker handling around UnwrapEmail fetch failures.
  • Cache preflight results briefly to reduce duplicate checks for repeated sends.
  • Add per-tenant send rate limits and abuse alerting.
  • Log blocked attempts with clear reason codes for auditability.
  • Add unit tests for allowed and blocked preflight outcomes.

Source