Skip to main content
RapidDev - Software Development Agency
App Featurespersonalization-ux19 min read

How to Add Email Integration to Your App — Copy-Paste Prompts Included

Email integration needs an API provider (Resend is the best starting point — 3,000 free emails/month), an Edge Function that fires on database events or user actions, HTML email templates built with react-email, and an email_preferences table so users control which emails they receive. Lovable wires this in 4–6 hours. Running cost is $0–20/month for most early-stage apps — cost only scales with email volume.

4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members

Feature spec

Intermediate

Category

personalization-ux

Build with AI

3–6 hours with Lovable

Custom build

3–5 days custom dev

Running cost

$0–20/mo up to 1K users

Works on

WebMobile

Everything it takes to ship Email Integration — parts, prompts, and real costs.

TL;DR

Email integration needs an API provider (Resend is the best starting point — 3,000 free emails/month), an Edge Function that fires on database events or user actions, HTML email templates built with react-email, and an email_preferences table so users control which emails they receive. Lovable wires this in 4–6 hours. Running cost is $0–20/month for most early-stage apps — cost only scales with email volume.

What Email Integration Actually Involves

Email integration is not just sending a message — it is a small system with four moving parts: a trigger (user signs up, order ships, a daily digest fires), an HTML template that renders your brand correctly in Gmail, Outlook, and Apple Mail, a delivery API that handles the SMTP plumbing and tracks bounces, and a preferences layer so users can unsubscribe from optional emails without losing critical transactional ones. The pieces that trip up first builds are DNS authentication (DKIM and SPF records), the difference between transactional and marketing email rules, and duplicate sends when Supabase Auth's built-in email fires alongside your custom Edge Function. Get those three right and email is a solved problem.

What users consider table stakes in 2026

  • Transactional emails (welcome, password reset, receipts) delivered within 5 seconds of the triggering event
  • HTML email templates visually matching the app's branding — logo, brand color, font stack
  • Unsubscribe link present in every marketing and digest email, with one-click opt-out
  • Bounce and delivery status visible in the admin dashboard — hard bounces suppressed automatically
  • Users can control which notification email types they receive via a preferences page in the app
  • Emails render correctly in Gmail, Outlook 365, and Apple Mail without broken layouts

Anatomy of the Feature

Seven components — two data tables, three backend functions, one UI layer, and one DNS service. AI tools build five of these reliably; DNS setup and delivery webhooks need careful attention.

Layers:UIDataBackendService

Email Trigger

Backend

A Supabase Edge Function (Deno runtime) that fires on database events via Supabase Webhooks or pg_net, or on direct user actions (button click → Server Action → Edge Function). Imports the Resend SDK (@resend/node) or calls the SendGrid REST API with the recipient, template name, and variable payload.

Note: Name your Edge Functions by email type: send-welcome-email, send-order-confirmation, send-weekly-digest. One function per email type makes debugging and selective disabling much easier.

HTML Email Template

UI

React Email components (react-email, @react-email/components) for reusable, testable email layouts. Each template is a React component that accepts variables (userName, orderTotal, ctaUrl) and is rendered server-side to an HTML string via renderAsync(). react-email's preview server lets you see template changes in a browser before sending.

Note: Email clients interpret CSS inconsistently — react-email handles this by generating inline styles and table-based layouts that survive Outlook's rendering engine. Do not use CSS Grid or Flexbox in email templates.

Email Preferences Table

Data

Supabase table email_preferences with boolean columns per email category: marketing, product_updates, transactional. The transactional flag should never disable truly critical emails (password reset, security alerts) — enforce this in the Edge Function logic, not the UI. Users manage their own row via a preferences page in the app.

Note: Add a preferences link to every email footer that takes the user directly to their preferences page — this reduces unsubscribe-all actions because users can opt out of marketing while keeping transactional.

Unsubscribe Handler

Backend

A Supabase Edge Function or Next.js API route that receives unsubscribe link clicks. The link contains a signed JWT (HMAC-SHA256) encoding the user_id and email_type — no login required to unsubscribe. The handler validates the JWT, flips the relevant boolean in email_preferences, and returns a confirmation page.

Note: CAN-SPAM and GDPR both require one-click unsubscribe to work without requiring login. The signed JWT prevents unauthorized unsubscribes while keeping the flow frictionless.

Delivery Webhook Receiver

Backend

An Edge Function endpoint registered with Resend or SendGrid to receive real-time delivery events: delivered, bounced, complained, opened. Inserts events into email_delivery_log. On hard bounce, sets a suppressed flag on the user record to prevent future sends. Alerts admin for unusual bounce spike.

Note: Register this endpoint in the Resend dashboard under Webhooks immediately after setup — without it, you have no visibility into delivery failures and bounced users will keep receiving retried sends.

Admin Email Log

Data

Supabase table email_delivery_log recording every email send attempt with its outcome: provider_message_id, status (sent, delivered, bounced, complained), delivered_at, opened_at. Drives an admin deliverability dashboard showing per-template delivery rates and flagging users with bounced addresses.

Note: Index on (user_id, sent_at DESC) for the per-user email history view and on (status, sent_at DESC) for the admin deliverability overview.

DKIM/SPF DNS Records

Service

TXT DNS records added to your sending domain in your domain registrar. DKIM (DomainKeys Identified Mail) signs each email with a cryptographic key that receiving mail servers verify against your DNS. SPF (Sender Policy Framework) lists the servers authorized to send mail from your domain. Both are required for reliable Gmail inbox delivery — without them, emails land in spam.

Note: Propagation takes up to 48 hours. Verify both records using MXToolbox before sending to real users. Resend dashboard → Domains shows setup status with green/red indicators.

The data model

Two tables: email_preferences for user opt-in/out control, and email_delivery_log for admin deliverability visibility. Run this in the Supabase SQL editor.

schema.sql
1create table public.email_preferences (
2 user_id uuid references auth.users on delete cascade primary key,
3 marketing bool not null default true,
4 product_updates bool not null default true,
5 transactional bool not null default true,
6 updated_at timestamptz not null default now()
7);
8
9alter table public.email_preferences enable row level security;
10
11create policy "Users can view own email preferences"
12 on public.email_preferences for select
13 using (auth.uid() = user_id);
14
15create policy "Users can upsert own email preferences"
16 on public.email_preferences for insert
17 with check (auth.uid() = user_id);
18
19create policy "Users can update own email preferences"
20 on public.email_preferences for update
21 using (auth.uid() = user_id);
22
23create table public.email_delivery_log (
24 id uuid primary key default gen_random_uuid(),
25 user_id uuid references auth.users on delete set null,
26 template_name text not null,
27 provider_message_id text,
28 status text not null default 'sent',
29 error_message text,
30 sent_at timestamptz not null default now(),
31 delivered_at timestamptz,
32 opened_at timestamptz
33);
34
35alter table public.email_delivery_log enable row level security;
36
37create policy "Service role can insert delivery log"
38 on public.email_delivery_log for insert
39 to service_role
40 with check (true);
41
42create policy "Service role can update delivery log"
43 on public.email_delivery_log for update
44 to service_role
45 using (true);
46
47create index email_log_user_idx
48 on public.email_delivery_log (user_id, sent_at desc);
49
50create index email_log_status_idx
51 on public.email_delivery_log (status, sent_at desc);

Heads up: The service_role INSERT/UPDATE policy on email_delivery_log lets your Edge Functions (which use the service role key) write delivery events without exposing the log to regular users. Admins query it directly from the Supabase dashboard.

Build it — pick your path

Each tool fits this feature differently. Switch tabs to compare fit, time, the exact steps, and a copy-paste prompt.

Hand-built by developersFit for this feature:

Full custom build is the right choice when email is a core product feature — newsletter platforms, email clients, transactional systems requiring A/B testing, dedicated IPs, or multi-provider failover.

Step by step

  1. 1Build a template management system where HTML email templates are stored as database rows and editable without code deploys
  2. 2Implement SendGrid Dynamic Templates for A/B testing subject lines and CTA copy with statistical significance tracking
  3. 3Set up dedicated IP pools in SendGrid with a warm-up schedule for high-volume sending to protect sender reputation
  4. 4Build a suppression list synced across providers so a hard bounce in Resend prevents SendGrid fallover from resending

Where this path bites

  • Dedicated IP warm-up (sending volume that ramps over 4–6 weeks) adds significant ops overhead before production sending begins
  • Full deliverability setup (DKIM, SPF, DMARC, BIMI) plus reputation monitoring is a week of standalone work separate from feature development

Third-party services you'll need

Email sending requires a third-party API — you cannot send production email reliably without one. DNS authentication is a one-time free setup in your domain registrar.

ServiceWhat it doesFree tierPaid from
ResendPrimary transactional email API — simplest integration, excellent developer experience, built-in react-email support3,000 emails/month, 100 emails/dayPro $20/mo (50K emails); Business $90/mo (100K emails) (approx)
SendGridAlternative to Resend — larger ecosystem, Dynamic Templates for A/B testing, dedicated IP options for high volume100 emails/day (no monthly cap on free tier)Essentials $19.95/mo (50K emails); Pro $89.95/mo (150K emails) (approx)
react-emailOpen-source React component library for building cross-client compatible HTML email templatesFully free (MIT license)Free — no paid tier
Supabase pg_netBuilt-in HTTP extension for calling email APIs directly from PostgreSQL database triggers and functionsIncluded in all Supabase plansNo additional cost — included in Supabase Pro ($25/mo) (approx)

Swipe the table sideways to see pricing.

What it costs to run

Drag through the tiers to see how your monthly bill scales with users — no surprises later.

Estimated monthly running cost

$0/mo

Resend free tier (3,000 emails/month) easily covers welcome + transactional for 100 users. Supabase free tier handles email_preferences and delivery log storage.

Estimates use verified 2026 pricing and assume typical usage per user. Your real bill depends on activity, storage, and third-party plans.

What breaks when AI tools build this

The failures people actually hit on their first build — the symptom, why it happens, and the exact fix.

Emails go straight to Gmail spam

Symptom: DKIM and SPF DNS records are not configured for the sending domain. Emails arrive from Resend's shared IP pool without domain authentication — Gmail's spam filter flags them as potentially spoofed. This is the single most common email integration failure and it is invisible in development because you see 'sent' status in the API but recipients never see the message.

Fix: Go to the Resend dashboard → Domains → Add Domain, then copy the two DKIM TXT records and the SPF TXT record shown there into your domain registrar's DNS settings. Wait up to 48 hours for propagation, then verify at MXToolbox (search your domain with the TXT check). All three records must show green before sending to real users.

Users receive two welcome emails after signup

Symptom: Supabase Auth has built-in email confirmation enabled by default — it sends a welcome/confirmation email immediately on signup. If your custom Edge Function also fires on the auth.users insert event, the user gets both emails within seconds. This burns sender reputation and confuses users.

Fix: Decide which system owns email: either use Supabase Auth's built-in templates (configure them in Supabase dashboard → Authentication → Email Templates) or disable them and own all emails yourself via Edge Functions. To disable: Authentication → Email Templates → toggle off 'Confirm signup'. Do not run both.

Unsubscribe link returns 404 after deployment

Symptom: The unsubscribe Edge Function was generated but its URL was not set as an environment variable in the deployed app, or the function was not deployed to production (it exists locally but not on Supabase). The signed JWT in the unsubscribe URL contains an expiry, so old links also fail after the default 24-hour window.

Fix: Verify the Edge Function is deployed: open Supabase dashboard → Edge Functions and confirm the function shows 'Active' status. Add UNSUBSCRIBE_SECRET to Supabase Secrets (Cloud tab in Lovable, or Supabase dashboard → Edge Functions → Secrets). Set JWT expiry to 30 days in the signing code so links in weekly digests remain valid.

Edge Function times out sending emails with large templates

Symptom: react-email's renderAsync() compiles large templates with many conditional sections on every invocation. In cold-start Edge Functions (which have no warm state), this compilation takes 8–15 seconds, exceeding the default 10-second Edge Function timeout and causing a 504 error.

Fix: Pre-render templates at build time into static HTML strings stored in Supabase Storage as .html files. The Edge Function fetches the pre-rendered HTML and performs string replacement for variables ({{userName}}, {{ctaUrl}}) rather than re-rendering the React component. This reduces per-send execution time from 10+ seconds to under 1 second.

Best practices

1

Use Resend for new projects — the developer experience, react-email native support, and 3,000 free emails/month make it the default choice for apps under 50K monthly sends

2

Never store RESEND_API_KEY or SendGrid keys in frontend code — always use Supabase Secrets (Edge Functions) or Vercel env vars (Next.js API routes), server-side only

3

Set up DKIM and SPF DNS records before sending to any real user — spam folder delivery poisons your sender reputation in the first 24 hours

4

Keep the transactional boolean in email_preferences always true for critical flows (password reset, security alerts) — only marketing and product_updates should be user-toggleable

5

Add the unsubscribe URL with a signed JWT to every marketing and digest email footer — CAN-SPAM and GDPR both require one-click unsubscribe with no login barrier

6

Cache the email_preferences lookup in your Edge Function using the session — don't query the table for every send in a batch digest run

7

Log every send attempt to email_delivery_log before the API call, then update status on the webhook callback — this gives you a complete audit trail even if the API call times out

8

Pre-render react-email templates to static HTML at build time and store in Supabase Storage — cold-start template compilation causes Edge Function timeouts at scale

When You Need Custom Development

Lovable and V0 handle standard transactional email integration reliably. These scenarios require deeper engineering:

  • The app is itself a newsletter or email client product requiring full inbox management, IMAP/SMTP integration, or email threading
  • Regulatory requirement to maintain CAN-SPAM and GDPR-compliant suppression lists with full audit trail and data export capability
  • High-volume sending (100,000+ emails per day) requiring dedicated IP pools, a warm-up schedule over 4–6 weeks, and reputation monitoring
  • Transactional email templates need A/B testing, send-time optimization, and engagement analytics beyond basic open/click tracking

RapidDev builds these features for production

Real auth, database, and payments — fixed price, delivered in weeks. You own 100% of the code.

Get a fixed-price quote

Frequently asked questions

Which email provider is best for a new app — Resend or SendGrid?

Resend for most new projects. It has native react-email support, a cleaner API, and 3,000 free emails per month with no daily cap limits as restrictive as SendGrid's 100/day free tier. SendGrid makes more sense if you need Dynamic Templates for A/B testing subject lines, dedicated IP management for high-volume sending, or if your team already has a SendGrid account with sender reputation built up.

Do I need to verify my domain to send emails?

Yes, for production. You can send from an unverified domain during development, but emails will land in spam for most recipients. Domain verification means adding two DKIM TXT records and one SPF TXT record to your domain's DNS — Resend's dashboard shows you exactly what to copy. Allow up to 48 hours for DNS propagation before testing deliverability.

What is the difference between transactional and marketing emails?

Transactional emails are sent in direct response to a user action — welcome email after signup, password reset, order confirmation, security alert. Marketing emails are sent proactively — weekly digests, promotional campaigns, product announcements. CAN-SPAM and GDPR apply stricter rules to marketing emails (mandatory unsubscribe, no deceptive headers) while transactional emails have more flexibility. Never put a user into a 'no email' state that blocks their password reset.

How do I stop emails going to spam?

Three steps cover 95% of spam filter failures: (1) Set up DKIM and SPF records for your sending domain — do this before your first production send. (2) Start with low volume and gradually increase to build sender reputation. (3) Maintain a clean list by suppressing hard bounces immediately and processing unsubscribes within 10 days as required by CAN-SPAM. Gmail's Postmaster Tools dashboard shows your domain reputation once volume picks up.

Can users unsubscribe from specific email types?

Yes — the email_preferences table stores boolean flags per category (marketing, product_updates, transactional). Each category maps to a toggle in your app's notification settings page. The unsubscribe link in email footers should specify which category to unsubscribe from, not silently disable all email. Transactional should always remain true unless the user explicitly requests account deletion.

How do I preview my email template before sending?

react-email includes a local preview server — run it in a separate browser tab outside your main app to see templates rendered with test data. The Resend dashboard also shows a preview of recent sends in the Logs tab. For cross-client testing (Gmail vs Outlook vs Apple Mail rendering), Litmus or Email on Acid provide screenshot previews across 90+ clients — useful before a major launch but not required for every iteration.

What happens when an email bounces?

Hard bounces (permanent delivery failure — the address doesn't exist) should be recorded in email_delivery_log with status 'bounced' and suppressed from all future non-critical sends. Soft bounces (temporary failure — mailbox full) can be retried 2–3 times over 24 hours. Resend and SendGrid both send bounce events to your registered webhook endpoint automatically — your delivery webhook Edge Function updates the log.

Is there a free tier that covers small apps?

Resend's free tier (3,000 emails/month, 100/day) covers welcome and transactional emails for apps under roughly 300 active users sending 10 emails each per month. The 100/day cap matters if you trigger batch sends — a welcome email campaign for 200 new users in a day would hit the cap. Upgrade to Resend Pro ($20/mo, approx) when you add weekly digests or the user base grows past 300.

RapidDev

Need this feature production-ready?

RapidDev builds email integration into real apps — auth, database, payments — at $13K–$25K.

Book a free consultation

30-min call. No commitment.

Want this built for you?

We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

Get a fixed-price quote

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.