New from emailrHealthCheck Email iconHealthCheck Email
emailr_

Send email from Supabase with emailr_

Send transactional and auth email from Supabase Edge Functions with emailr_, including a Send Email auth hook for branded signup and magic-link emails.

Supabase iconSupabasePlatform

Supabase Edge Functions run on Deno and can import the emailr npm package directly. This guide covers two jobs: sending app email from an Edge Function, and replacing Supabase Auth's built-in emails with your own through the Send Email hook.

Both run inside your Supabase project, so there's no extra server to deploy.

Set up emailr_ with Supabase

  1. 01

    Create an API key

    Create a key under API keys in the dashboard. Keys start with et_live_ and are scoped to one domain workspace. Store it as EMAILR_API_KEY in your secret manager or environment, never in client-side code.

  2. 02

    Add and verify your sending domain

    In the dashboard, open Domains and add the domain you send from. A subdomain such as mail.yourcompany.com keeps transactional reputation separate from your corporate mailbox.

    Emailr generates the DNS records: a DKIM TXT record on the emailr._domainkey selector, an SPF TXT record, and an MX + TXT pair on the send subdomain used as the MAIL FROM / Return-Path. A DMARC record is optional but recommended.

    Emailr's DKIM selector and send subdomain don't collide with other providers' records, so you can add them before cutting over and send from both providers during the migration. A domain can only have one SPF record: if one already exists, merge Emailr's include: into it instead of adding a second record.

  3. 03

    Store the key as a secret

    Edge Function secrets are exposed through Deno.env. Set the key with the Supabase CLI.

    Terminalbash
    supabase secrets set EMAILR_API_KEY=et_live_...
  4. 04

    Send from an Edge Function

    Import the SDK with an npm: specifier. Call the function from your app with supabase.functions.invoke('send-email', { body }), or from a Database Webhook when a row is inserted.

    supabase/functions/send-email/index.tsts
    import { Emailr } from 'npm:emailr'
    
    const emailr = new Emailr({ apiKey: Deno.env.get('EMAILR_API_KEY')! })
    
    Deno.serve(async (req) => {
      const { to, name } = await req.json()
    
      const result = await emailr.emails.send({
        from: 'Acme <[email protected]>',
        to,
        subject: `Welcome, ${name}`,
        html: `<p>Hi ${name}, your workspace is ready.</p>`,
      })
    
      return Response.json({ id: result.message_id })
    })
  5. 05

    Replace Auth emails with the Send Email hook

    In the dashboard, open Authentication → Hooks, add a Send Email hook of type HTTPS pointing at your function, and copy the generated secret into SEND_EMAIL_HOOK_SECRET. Supabase signs hook requests with Standard Webhooks, and the payload contains the user plus email_data with the token hash and action type.

    Deploy this function with supabase functions deploy send-email-hook --no-verify-jwt, because the hook authenticates with its own signature rather than a user JWT.

    supabase/functions/send-email-hook/index.tsts
    import { Webhook } from 'https://esm.sh/[email protected]'
    import { Emailr } from 'npm:emailr'
    
    const emailr = new Emailr({ apiKey: Deno.env.get('EMAILR_API_KEY')! })
    const hookSecret = Deno.env.get('SEND_EMAIL_HOOK_SECRET')!.replace('v1,whsec_', '')
    
    Deno.serve(async (req) => {
      const payload = await req.text()
      const headers = Object.fromEntries(req.headers)
      const { user, email_data } = new Webhook(hookSecret).verify(payload, headers) as {
        user: { email: string }
        email_data: { token_hash: string; redirect_to: string; email_action_type: string }
      }
    
      const link = `${Deno.env.get('SUPABASE_URL')}/auth/v1/verify?token=${email_data.token_hash}` +
        `&type=${email_data.email_action_type}&redirect_to=${email_data.redirect_to}`
    
      await emailr.emails.send({
        from: 'Acme <[email protected]>',
        to: user.email,
        subject: 'Confirm your email',
        html: `<p><a href="${link}">Confirm your email address</a></p>`,
      })
    
      return Response.json({})
    })

Tips

  • Branch on email_action_type (signup, magiclink, recovery, invite, email_change) to send a different subject and template for each.
  • Returning a non-2xx status from the hook makes Supabase Auth report the failure to the user, so let SDK errors propagate.
  • SUPABASE_URL is available in Edge Functions by default.

Frequently asked questions

Can I use emailr_ for Supabase Auth emails?

Yes. Configure a Send Email auth hook that points at an Edge Function, verify the Standard Webhooks signature, and send the confirmation or magic link through emailr_.

Does the emailr_ SDK work in Supabase Edge Functions?

Yes. Import it with the npm:emailr specifier. It uses fetch and runs on Deno without extra configuration.

Do I still need Supabase's SMTP settings?

No. With the Send Email hook enabled, Supabase Auth calls your function instead of sending email itself.

How do I send email when a database row changes?

Create a Database Webhook on the table that calls your Edge Function, and send from the function with the row data in the request body.

Start sending in minutes

Create a free account, verify your domain and send your first email. No credit card required.