Start a Project
All guides

Dev Stack

Resend email setup for South African senders.

Most South African SaaS and ecommerce builders reach for SendGrid out of habit, then spend a day fighting the UI. Resend is the cleaner option — a clean API, React Email templates, and domain verification that completes in 10 minutes instead of 48 hours. For a .co.za sender, the hard part is not Resend itself, it is getting your DNS right at Afrihost, Xneelo or Cloudflare so that SPF, DKIM and DMARC align, and doing it in a way that does not send your first batch straight to the iAfrica, Mweb and Webmail junk folders. This guide walks the setup we use for our own transactional email (hi@ecomsolve.co.za), including POPIA-friendly double opt-in and the warming schedule we run for cold .co.za sender domains. Pricing is USD — the free tier covers 3,000 emails/month, Pro is $20/month for 50k — so budget for exchange-rate swings.

Updated 15 April 2026 · 10 min read · any · Joshua Kaplan

Prerequisites

  • A .co.za or .com domain you own and can edit DNS for
  • A Resend account (free plan to start)
  • DNS access on Cloudflare, Afrihost, Xneelo or wherever the domain is hosted
  • A basic understanding of SPF, DKIM and DMARC (or patience to read)
  • Somewhere to send from — a Node backend, Cloudflare Worker, or Next/Remix route

Step 1. Create a Resend account and add your domain

Sign up at resend.com, then Domains → Add Domain. Enter yoursite.co.za (not a subdomain for primary transactional unless you have a reason). Resend will show DNS records — one TXT for domain verification, one TXT for SPF, one or two CNAMEs for DKIM, one TXT for DMARC, and an MX for the reply-to if you enable inbound.

Step 2. Add the DNS records in Cloudflare (or your registrar)

If your DNS is on Cloudflare, set the DKIM CNAME to DNS only (grey cloud) — orange-cloud proxying will break DKIM signing. SPF goes as TXT; if you already have SPF for Google Workspace or Zoho, merge them into one record — multiple SPF records fail validation.

DNS records
# Domain verification
TXT  @                 resend-verify=abc123...

# SPF (merge with existing if you have Google/Zoho)
TXT  @                 v=spf1 include:_spf.resend.com include:_spf.google.com ~all

# DKIM (grey cloud on Cloudflare)
CNAME resend._domainkey  resend._domainkey.resend.com
CNAME resend2._domainkey resend2._domainkey.resend.com

# DMARC (start on p=none, tighten later)
TXT  _dmarc            v=DMARC1; p=none; rua=mailto:dmarc@yoursite.co.za; pct=100

Step 3. Verify and wait for DNS propagation

Click Verify in Resend. On Cloudflare, records propagate in under 2 minutes. On Afrihost or older SA DNS hosts, allow 30–60 minutes. If verification fails, check that SPF is a single record — a second SPF TXT (e.g. from an old Mailchimp setup) silently breaks alignment.

Step 4. Create an API key scoped to sending

Resend → API Keys → Create API Key. Scope it to Sending access only, not Full access, and name it after the environment (prod-transactional, staging-transactional). Store it in your secret manager — Cloudflare Workers Secrets, Fly.io secrets, Vercel environment variables.

Step 5. Send your first email from a Cloudflare Worker

Resend has a clean REST API. From a Cloudflare Worker running at the JNB or CPT PoP, the outbound request to api.resend.com lands in Ireland; delivery to a .co.za recipient (iAfrica, Mweb, Webmail, Gmail) is typically under 5 seconds end-to-end.

worker/src/send.ts
export async function sendWelcomeEmail(env: Env, to: string, firstName: string) {
  const res = await fetch('https://api.resend.com/emails', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${env.RESEND_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      from: 'EcomSolve <hi@ecomsolve.co.za>',
      to: [to],
      subject: 'Welcome to EcomSolve',
      reply_to: 'josh@ecomsolve.co.za',
      html: `<p>Hi ${firstName}, thanks for signing up.</p>
             <p><a href="https://ecomsolve.co.za/unsubscribe?email=${encodeURIComponent(to)}">Unsubscribe</a></p>`,
    }),
  });
  if (!res.ok) throw new Error(`Resend ${res.status}: ${await res.text()}`);
  return res.json();
}

Step 6. Use React Email for templates

Hand-maintained HTML email breaks on Outlook, Webmail and the SA ISP webmail clients. React Email compiles components to table-based HTML that renders correctly across clients. Pair it with Resend using the react: prop or render to HTML before sending.

emails/welcome.tsx
import { Html, Head, Body, Container, Text, Button, Link } from '@react-email/components';

export function WelcomeEmail({ firstName, unsubscribeUrl }: { firstName: string; unsubscribeUrl: string }) {
  return (
    <Html>
      <Head />
      <Body style={{ fontFamily: 'Arial, sans-serif', background: '#f3efe5' }}>
        <Container style={{ padding: 24, maxWidth: 560 }}>
          <Text>Hi {firstName},</Text>
          <Text>Thanks for signing up to EcomSolve.</Text>
          <Button href="https://ecomsolve.co.za/dashboard" style={{ background: '#e84a0c', color: '#fff', padding: '12px 20px' }}>
            Open dashboard
          </Button>
          <Text style={{ fontSize: 12, color: '#6b6b6b', marginTop: 32 }}>
            <Link href={unsubscribeUrl}>Unsubscribe</Link> · EcomSolve Pty Ltd, Cape Farms 7441
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

Step 7. Implement POPIA-compliant double opt-in for marketing

POPIA Section 69 restricts direct marketing to existing customers or people who gave consent. Transactional email (order confirmations, password resets) does not need opt-in. Newsletters and promotions do — send a confirmation email with a unique token and only add the address to your marketing list after they click. Keep the consent timestamp and IP in your DB for audit.

Step 8. Warm a new .co.za sender domain

A fresh domain sending 5,000 emails on day one will land in the spam folder at Webmail, iAfrica and even Gmail. Start with 50 emails/day to your most engaged users for three days, then 200/day, then 1,000/day, doubling every 3 days until you hit steady state. Monitor Resend → Analytics for bounce rate (keep under 2%) and complaint rate (under 0.1%).

Step 9. Tighten DMARC once stable

After two weeks of clean sending and reading your DMARC aggregate reports, move p=none → p=quarantine (spam folder for unaligned mail) → eventually p=reject. Full DMARC enforcement protects your .co.za domain from spoofing, which is increasingly common against SA brands.

SA gotchas

  • Cloudflare orange-cloud (proxy) on the DKIM CNAME breaks DKIM signing — Cloudflare rewrites the response. Set DKIM records to DNS only (grey cloud). This bites almost everyone once.
  • Two SPF records silently break alignment. If you previously sent through Google Workspace, Zoho or Mailchimp, merge the include: directives into one TXT, not two.
  • iAfrica, Mweb and Webmail are aggressive with new-domain filtering. Warm gradually and ask your first recipients to mark you as not-spam. A single bulk send on day one can blacklist you at these providers for weeks.
  • Cloudflare Workers cannot SMTP — no port 25 outbound. You must use the Resend HTTP API (or Postmark, or SES via HTTP). Do not try to run nodemailer on a Worker.
  • From: and Reply-To: can differ, but Gmail shows "via resend.com" if your DKIM is not set up correctly — it looks unprofessional to SA recipients. Verify DKIM passes before your first production send.
  • Resend bills in USD monthly. Free tier is 3,000 emails/month with a 100/day cap; Pro is $20/month for 50k. SA recipients count the same as global ones. Budget for ZAR volatility if you are at Pro scale.

Frequently asked questions

Is Resend POPIA-compliant for South African senders?

Resend is a processor under POPIA. You are the responsible party — your obligation is to collect consent (for marketing), honour unsubscribes, keep records, and document the cross-border data transfer (Resend hosts in the US and Ireland). Include Resend in your privacy notice. Nothing about Resend itself blocks POPIA compliance.

Can I send from a .co.za domain or do I need .com?

A .co.za domain works exactly the same as .com for email. Deliverability depends on SPF/DKIM/DMARC alignment and sender reputation, not TLD. Plenty of SA businesses send hundreds of thousands of emails per month from .co.za addresses with zero delivery issues.

How does Resend compare to SendGrid for South African senders?

Resend has a cleaner API, better React Email support, and simpler domain verification. SendGrid has more mature deliverability analytics, dedicated IPs on cheaper plans, and longer track record with SA ISPs. For transactional volume under 100k/month, Resend usually wins on developer experience. For high-volume marketing, SendGrid or Postmark are worth a look.

Can I send from a Cloudflare Worker running at the JNB PoP?

Yes, and it is a good pattern. The Worker calls Resend via HTTP — no SMTP needed. Latency to api.resend.com from a JNB Worker is around 180ms (Ireland egress); delivery to a .co.za recipient inbox is typically under 5 seconds.

What is the unsubscribe requirement under POPIA?

POPIA requires a clear, free mechanism for recipients to opt out of direct marketing. One-click unsubscribe (an HTTPS link that processes the opt-out without requiring login) is the gold standard. Keep suppression lists forever — do not re-add unsubscribers even if they return to your site later.