Supabase SMTP Setup & Email Sending (Edge Functions Guide)
Set up Supabase SMTP for auth emails and use Edge Functions for transactional email. Complete guide with code examples for custom SMTP, database webhooks, and Deno.
To set up Supabase SMTP, go to Project Settings > Authentication > SMTP Settings and enter your SMTP provider's credentials. This replaces Supabase's default email service for all auth emails (password resets, magic links, confirmations). For custom emails beyond auth, use Edge Functions with an email API.
This guide covers both approaches with full code examples.
For Supabase Auth emails (SMTP): Configure custom SMTP in Project Settings > Authentication > SMTP Settings to send auth emails from your own domain.
For custom emails (Edge Functions):
supabase functions new send-emailsupabase secrets set SENDPIGEON_API_KEY=sp_live_xxx- Import
npm:sendpigeonand callpigeon.send()
Set Up Custom SMTP in Supabase
By default, Supabase sends auth emails (confirmations, password resets, magic links) through a shared email service. The deliverability is limited and the emails come from a generic address. Configuring custom SMTP lets you send these from your own domain.
Go to Project Settings > Authentication > SMTP Settings in the Supabase dashboard and enter:
| Setting | Value |
|---|---|
| Host | smtp.sendpigeon.dev |
| Port | 587 |
| Username | Your SendPigeon API key (sp_live_xxx) |
| Password | Your SendPigeon API key (same value) |
| Sender email | noreply@yourdomain.com |
| Sender name | Your App Name |
Make sure you've verified your domain with SendPigeon first — SPF, DKIM, and DMARC need to be in place before sending through custom SMTP.
Once configured, all Supabase Auth emails (confirmations, password resets, magic links, invite links) will send through your domain. This improves deliverability and lets you customize the sender address.
You can also customize the email templates in Authentication > Email Templates to match your brand.
Send Custom Emails with Edge Functions
For emails beyond auth flows — welcome sequences, order confirmations, notifications — use Supabase Edge Functions with the SendPigeon SDK.
Create an Edge Function
supabase functions new send-email
This creates supabase/functions/send-email/index.ts.
Set Your API Key
Store the API key as a secret:
supabase secrets set SENDPIGEON_API_KEY=sp_live_your_key_here
For local development, create supabase/functions/.env:
SENDPIGEON_API_KEY=sp_live_your_key_here
Send Email from a Supabase Edge Function
// supabase/functions/send-email/index.ts
import { SendPigeon } from "npm:sendpigeon";
const pigeon = new SendPigeon(Deno.env.get("SENDPIGEON_API_KEY")!);
Deno.serve(async (req) => {
if (req.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
const { to, name } = await req.json();
const { data, error } = await pigeon.send({
from: "hello@yourdomain.com",
to,
subject: `Hey ${name}!`,
html: `<h1>Welcome</h1><p>Thanks for signing up.</p>`,
});
if (error) {
return Response.json({ error: error.message }, { status: error.status ?? 500 });
}
return Response.json({ emailId: data.id });
});
Supabase Edge Functions use Deno.serve() — the built-in Deno HTTP server. No framework needed.
Send Welcome Email on User Signup
Trigger an email when a new user signs up by setting up a Database Webhook on the auth.users table:
// supabase/functions/welcome-email/index.ts
import { SendPigeon } from "npm:sendpigeon";
const pigeon = new SendPigeon(Deno.env.get("SENDPIGEON_API_KEY")!);
Deno.serve(async (req) => {
const payload = await req.json();
// Database Webhook payload for auth.users
const { email, raw_user_meta_data } = payload.record;
const name = raw_user_meta_data?.name || "there";
const { error } = await pigeon.send({
from: "hello@yourdomain.com",
to: email,
subject: `Welcome, ${name}!`,
html: `
<h1>Welcome to our app!</h1>
<p>Your account is ready. Here's what to do next:</p>
<ul>
<li>Complete your profile</li>
<li>Explore the dashboard</li>
</ul>
`,
});
if (error) {
console.error("Welcome email failed:", error.message);
return Response.json({ error: error.message }, { status: 500 });
}
return Response.json({ success: true });
});
Send Email on Database Change
Use Supabase Database Webhooks to send an email when a row is inserted. Set up the webhook in the Supabase dashboard (Database > Webhooks) to call your Edge Function on INSERT.
// supabase/functions/order-confirmation/index.ts
import { SendPigeon } from "npm:sendpigeon";
const pigeon = new SendPigeon(Deno.env.get("SENDPIGEON_API_KEY")!);
Deno.serve(async (req) => {
const { record } = await req.json();
// record contains the inserted row
const { customer_email, customer_name, order_id, total } = record;
const { error } = await pigeon.send({
from: "orders@yourdomain.com",
to: customer_email,
subject: `Order #${order_id} confirmed`,
html: `
<h1>Order Confirmed</h1>
<p>Hey ${customer_name}, your order #${order_id} for $${total} has been placed.</p>
<p>We'll notify you when it ships.</p>
`,
});
if (error) {
console.error("Order email failed:", error.message);
}
return Response.json({ success: true });
});
CORS for Browser Requests
If calling your Edge Function from a browser, add CORS headers:
// supabase/functions/_shared/cors.ts
export const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
// supabase/functions/contact/index.ts
import { SendPigeon } from "npm:sendpigeon";
import { corsHeaders } from "../_shared/cors.ts";
const pigeon = new SendPigeon(Deno.env.get("SENDPIGEON_API_KEY")!);
Deno.serve(async (req) => {
// Handle CORS preflight
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
const { name, email, message } = await req.json();
const { error } = await pigeon.send({
from: "contact@yourdomain.com",
to: "you@yourdomain.com",
subject: `Contact form: ${name}`,
html: `<p><strong>From:</strong> ${name} (${email})</p><p>${message}</p>`,
replyTo: email,
});
if (error) {
return Response.json({ error: "Failed to send" }, {
status: 500,
headers: corsHeaders,
});
}
return Response.json({ success: true }, { headers: corsHeaders });
});
Deploy
supabase functions deploy send-email
Your function is live at:
https://<project-id>.supabase.co/functions/v1/send-email
Call it with your Supabase anon key:
curl -X POST https://<project-id>.supabase.co/functions/v1/send-email \
-H "Authorization: Bearer YOUR_SUPABASE_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"to": "user@example.com", "name": "Johan"}'
Test Locally
Run your function locally:
supabase start
supabase functions serve send-email
The function runs at http://localhost:54321/functions/v1/send-email.
To catch emails locally instead of sending them, use the SendPigeon CLI:
npx @sendpigeon-sdk/cli dev
View captured emails at localhost:4100. See the local email testing guide for full setup.
Frequently Asked Questions
What runtime do Supabase Edge Functions use?
Supabase Edge Functions run on the Deno runtime. TypeScript and JavaScript work natively — no transpilation or build step. The runtime supports Web Standard APIs, Deno APIs, and npm packages via the npm: import prefix.
Can I use npm packages in Supabase Edge Functions?
Yes. Use the npm: prefix in your import: import { SendPigeon } from "npm:sendpigeon". No node_modules or package.json required — Deno resolves and caches the package automatically.
How do I store secrets in Supabase?
Run supabase secrets set SENDPIGEON_API_KEY=your_key to store secrets for production. Access them with Deno.env.get("SENDPIGEON_API_KEY"). For local development, place them in supabase/functions/.env.
Can I send email when a database row is inserted?
Yes. Set up a Database Webhook in the Supabase dashboard (Database > Webhooks) to trigger your Edge Function on INSERT, UPDATE, or DELETE. The function receives the row data in the request body.
Does SendPigeon work with Deno?
Yes. The SendPigeon SDK uses the Fetch API, which Deno supports natively. Import with npm:sendpigeon and it works the same as in Node.js.
Next Steps
- Set up DKIM, SPF, and DMARC on your sending domain
- Review the email deliverability checklist
- Build templates with our free visual email builder
- Browse our email templates for ready-to-use HTML
Other Platforms
Deploying elsewhere? We have guides for:
See all framework guides.