← Back to all posts

Kirim Email Konfirmasi Booking dengan MailAnvil + Express.js — Tutorial Lengkap

2026-07-25 · MailAnvil Team

Bayangkan: pelanggan Anda baru saja memesan tiket pesawat ke Bali lewat aplikasi Anda. Dalam hitungan detik, email konfirmasi beserta e-ticket harus sampai di inbox mereka. Kalau email terlambat atau masuk spam? Kepercayaan pelanggan langsung turun.

Ini masalah nyata yang dihadapi startup travel seperti Tiket.com, layanan food delivery seperti GoSend, atau platform OTP verifikasi di fintech seperti DANA. Mereka semua butuh email API yang cepat, andal, dan — yang paling penting — harganya masuk akal dalam Rupiah.

Di tutorial ini, kita akan bangun endpoint kirim email konfirmasi booking pakai MailAnvil dan Express.js. Siap?

Kenapa MailAnvil?

Sebelum ngoding, satu pertanyaan: kenapa nggak pakai SendGrid atau Resend?

Faktor SendGrid/Resend MailAnvil
Harga 100K email ~Rp 900rb (USD) Rp 599rb
Pembayaran Kartu kredit QRIS, GoPay, kartu kredit
Support Bahasa Inggris Bahasa Indonesia
Infrastruktur AWS US/EU AWS ap-southeast-1 (Jakarta latency rendah)
AI/Agent ready Tidak native MCP-native — AI agent langsung bisa pakai

Harga 2.4x lebih murah di volume 100K email. Untuk startup Indonesia yang kirim ribuan email per hari, selisih ini signifikan.

Prasyarat

Step 1: Setup Project

mkdir booking-email && cd booking-email
npm init -y
npm install express dotenv

Step 2: Dapatkan API Key

Login ke app.mailanvil.com, buka tab API Keys, dan generate key baru. Simpan di .env:

MAILANVIL_API_KEY=ma_key_xxxxxxxxxxxx

Step 3: Buat Email Service

Buat file email.js:

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

async function sendBookingEmail({ to, bookingId, customerName, details }) {
  const res = await fetch(`${MAILANVIL_API}/send`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.MAILANVIL_API_KEY}`,
      'Idempotency-Key': bookingId  // cegah kirim 2x
    },
    body: JSON.stringify({
      from: 'booking@travelokaclone.id',
      to: [to],
      subject: `Konfirmasi Booking #${bookingId} — ${details.route}`,
      html: `
        <div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
          <h1 style="color: #ff801f;">Booking Dikonfirmasi! ✅</h1>
          <p>Halo ${customerName},</p>
          <p>Booking Anda <strong>#${bookingId}</strong> sudah terkonfirmasi.</p>
          <table style="width: 100%; border-collapse: collapse; margin: 16px 0;">
            <tr><td style="padding: 8px; border-bottom: 1px solid #eee;">Rute</td><td style="padding: 8px; border-bottom: 1px solid #eee;"><strong>${details.route}</strong></td></tr>
            <tr><td style="padding: 8px; border-bottom: 1px solid #eee;">Tanggal</td><td style="padding: 8px; border-bottom: 1px solid #eee;">${details.date}</td></tr>
            <tr><td style="padding: 8px; border-bottom: 1px solid #eee;">Penumpang</td><td style="padding: 8px; border-bottom: 1px solid #eee;">${details.passengers}</td></tr>
            <tr><td style="padding: 8px;">Total</td><td style="padding: 8px;"><strong>Rp ${details.total.toLocaleString('id-ID')}</strong></td></tr>
          </table>
          <p>E-ticket terlampir dalam lampiran email ini.</p>
          <p style="color: #666; font-size: 12px;">Butuh bantuan? Balas email ini atau hubungi support@travelokaclone.id</p>
        </div>
      `,
      text: `Booking #${bookingId} dikonfirmasi. Rute: ${details.route}. Tanggal: ${details.date}. Total: Rp ${details.total.toLocaleString('id-ID')}`,
    })
  });

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

  return res.json();
}

module.exports = { sendBookingEmail };

Step 4: Buat Route Express

server.js:

require('dotenv').config();
const express = require('express');
const { sendBookingEmail } = require('./email');

const app = express();
app.use(express.json());

app.post('/api/booking', async (req, res) => {
  try {
    const { customerEmail, customerName, route, date, passengers, total } = req.body;

    // Generate booking ID
    const bookingId = `BK-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;

    // Simpan ke database... (mongodb, postgres, etc.)

    // Kirim email konfirmasi — fire-and-forget
    sendBookingEmail({
      to: customerEmail,
      bookingId,
      customerName,
      details: { route, date, passengers, total }
    }).catch(err => console.error('Email failed:', err));

    res.json({ bookingId, status: 'confirmed' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3000, () => console.log('Server running on http://localhost:3000'));

Step 5: Uji Coba

curl -X POST http://localhost:3000/api/booking \
  -H "Content-Type: application/json" \
  -d '{
    "customerEmail": "pelanggan@example.com",
    "customerName": "Budi Santoso",
    "route": "Jakarta (CGK) → Bali (DPS)",
    "date": "15 Agustus 2026",
    "passengers": 2,
    "total": 2450000
  }'

Response:

{ "bookingId": "BK-1753459200000-x7k2m", "status": "confirmed" }

Email langsung terkirim. Cek dashboard MailAnvil untuk lihat status delivery (delivered/bounced/complaint).

Use Case Lain: Bukan Cuma Travel

Pola yang sama bisa dipakai untuk:

Semua pakai API yang sama: POST /v1/send.

Tips Produksi

  1. Selalu pakai Idempotency-Key — cegah email terkirim 2x kalau retry. Pakai booking ID sebagai key.
  2. Verifikasi domain dulu — DKIM wajib. Tanpa itu, email masuk spam.
  3. Pantau dashboard bounce rate — MailAnvil punya kill switch otomatis kalau bounce >5%.
  4. Gunakan template — API MailAnvil support template CRUD. Simpan HTML di server MailAnvil, panggil via template_id.
  5. Webhook untuk status delivery — daftarkan webhook untuk tracking real-time: delivered, bounced, complaint.

Mulai Gratis

MailAnvil punya Free Plan: 500 email/bulan. Cukup untuk development dan testing. Daftar di mailanvil.com — nggak perlu kartu kredit. Pembayaran pakai QRIS atau GoPay.

Untuk startup yang sudah production, Starter Plan 10.000 email cuma Rp 149rb/bulan. Harga lokal, support lokal, infrastruktur lokal.


Dokumentasi lengkap: docs.mailanvil.com MCP Server: mcp.mailanvil.com Dashboard: app.mailanvil.com