← Back to all posts
2026-08-17 · MailAnvil Team

Kirim Email Transaksional dari Cloudflare Workers dengan MailAnvil + Hono

Startup Indonesia makin banyak deploy di Cloudflare Workers — latency Jakarta di bawah 10ms, scale otomatis, nggak kelola server. Tapi begitu butuh kirim email transaksional, banyak yang balik ke solusi lama: spin VPS, install nodemailer, pusing SMTP relay.

Nggak perlu. Kalau backend kamu di edge, email juga harus dari edge. Tutorial ini bangun endpoint kirim email pakai Hono + MailAnvil, langsung jalan di Cloudflare Workers.

Kenapa MailAnvil untuk Workers?

MailAnvil sendiri dibangun di atas CF Workers. Satu ekosistem, satu mental model.

MailAnvil Resend SendGrid
Harga 10K email Rp 149rb/bln ~Rp 320rb ~Rp 319rb
Pembayaran QRIS, GoPay Kartu kredit Kartu kredit
Docs Bahasa + English English English
Runtime CF Workers native Node SDK Node SDK
AI agent MCP-native Ada Ada

Untuk tim yang udah di ekosistem Cloudflare, MailAnvil nggak maksa kamu pindah stack. API-nya REST biasa, bisa dipanggil dari worker manapun.

Yang Kita Bangun

Flow minimal:

POST /send-email → Hono Worker (edge Jakarta) → MailAnvil /v1/send → inbox user

User request masuk ke worker terdekat, email keluar dari region yang sama. Nggak ada hop ke AWS us-east-1.

Step 1: Setup Project Hono

npm create hono@latest mailanvil-worker
cd mailanvil-worker
npm install

Step 2: Secret API Key

Simpan key sebagai secret Workers (jangan hardcode):

npx wrangler secret put MAILANVIL_API_KEY

Step 3: Email Sender

src/email.ts:

const BASE = 'https://api.mailanvil.com/v1';

export async function sendEmail(payload: {
  to: string;
  subject: string;
  html: string;
  text: string;
  idempotencyKey?: string;
}) {
  const res = await fetch(`${BASE}/send`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.MAILANVIL_API_KEY}`,
      ...(payload.idempotencyKey ? { 'Idempotency-Key': payload.idempotencyKey } : {}),
    },
    body: JSON.stringify({
      from: '[email protected]',
      to: [payload.to],
      subject: payload.subject,
      html: payload.html,
      text: payload.text,
    }),
  });

  if (res.status === 202) return res.json();
  const err = await res.json();
  throw new Error(err.error?.message || `MailAnvil ${res.status}`);
}

Step 4: Route Handler

src/index.ts:

import { Hono } from 'hono';
import { sendEmail } from './email';

const app = new Hono();

app.post('/send-otp', async (c) => {
  const { email, otp } = await c.req.json();
  if (!email || !otp) return c.json({ error: 'email dan otp wajib' }, 400);

  try {
    await sendEmail({
      to: email,
      subject: 'Kode Verifikasi Kamu',
      html: `<h1 style="color:#ff801f">Kode OTP: <strong>${otp}</strong></h1>`,
      text: `Kode OTP kamu: ${otp}`,
      idempotencyKey: `${email}-${Date.now()}`,
    });
    return c.json({ success: true });
  } catch (e) {
    return c.json({ error: 'Gagal kirim OTP' }, 500);
  }
});

export default app;

Step 5: Deploy & Test

npx wrangler deploy
curl -X POST https://mailanvil-worker.namakamu.workers.dev/send-otp \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","otp":"482913"}'

Response {"success":true}. Email masuk dalam <1 detik dari region Jakarta.

Use Case Nyata di Indonesia

Pola yang sama dipakai tiga skenario paling umum:

Semua lewat satu endpoint: POST /v1/send.

Best Practices

  1. Idempotency-Key wajib. Workers bisa retry request saat timeout. Tanpa key, user dapat email dobel.
  2. Secret, bukan env publik. Pakai wrangler secret put, jangan commit key ke repo.
  3. Verifikasi domain dulu. DKIM wajib biar email nggak masuk spam. MailAnvil auto-setup DKIM buat domain di Cloudflare.
  4. Pantau bounce. Kill switch otomatis aktif kalau bounce >5%. Jaga reputasi domain.

Mulai Gratis

Free plan 500 email/bulan, tanpa kartu kredit. Pembayaran QRIS/GoPay. Docs Bahasa Indonesia lengkap.

➡️ Coba MailAnvil Gratis — mailanvil.com