Cara Kirim Email Notifikasi Pembayaran dengan MailAnvil + Node.js
Setiap transaksi digital di Indonesia butuh email notifikasi. Entah itu invoice GoFood, konfirmasi pesanan Tokopedia, atau OTP BCA Mobile — email adalah jalur komunikasi paling resmi antara aplikasi dan pengguna.
Masalahnya: kebanyakan developer Indonesia pakai SendGrid atau Resend. Harganya dalam USD. Setiap bulan kena konversi kurs + biaya kartu kredit internasional. Untuk startup baru yang baru dapat 1000 transaksi per bulan, ini membengkak diam-diam.
MailAnvil hadir dengan harga Rupiah, pembayaran QRIS/GoPay, dan API standar REST. Artikel ini akan nunjukin cara kirim email notifikasi pembayaran kurang dari 10 menit.
Kenapa Email Notifikasi Pembayaran Penting
Tiga use case paling umum di aplikasi Indonesia:
- Food delivery — GoFood, GrabFood kirim invoice + rincian pesanan via email
- E-commerce — Tokopedia, Shopee kirim konfirmasi pesanan + link lacak pengiriman
- Fintech — OVO, Dana kirim bukti transfer + mutasi digital
Semua skenario ini pakai transactional email — email yang trigger otomatis dari aksi user, bukan marketing blast.
Prasyarat
- Akun MailAnvil (daftar gratis di mailanvil.com)
- Node.js 18+ terinstall
- Domain terverifikasi di MailAnvil (untuk production)
Langkah 1: Setup Proyek Express.js
mkdir payment-notifier && cd payment-notifier
npm init -y
npm install express dotenv
Buat file .env:
MAILANVIL_API_KEY=ma_your_api_key_here
MAILANVIL_API_URL=https://api.mailanvil.com/v1
Langkah 2: Buat Fungsi Pengirim Email
Buat mailer.js:
// mailer.js — MailAnvil email sender
const MAILANVIL_URL = process.env.MAILANVIL_API_URL;
async function sendPaymentNotification({ to, customerName, orderId, amount, items }) {
const response = await fetch(`${MAILANVIL_URL}/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MAILANVIL_API_KEY}`,
'Idempotency-Key': orderId // ⬅️ anti-duplikasi
},
body: JSON.stringify({
from: 'noreply@aplikasimu.com',
to: [to],
subject: `Pembayaran Berhasil — Pesanan #${orderId}`,
html: buildInvoiceHTML({ customerName, orderId, amount, items }),
text: `Halo ${customerName}, pembayaran Rp${amount.toLocaleString('id-ID')} untuk pesanan #${orderId} telah berhasil.`
})
});
if (!response.ok) {
const err = await response.json();
throw new Error(`MailAnvil error: ${err.error?.message || response.status}`);
}
return response.json();
}
Poin penting:
- Header Idempotency-Key dengan orderId — mencegah kirim email dua kali kalau request retry
- Selalu sediakan versi text selain html — deliverability lebih baik
- Format Rupiah pakai toLocaleString('id-ID')
Langkah 3: Template Invoice HTML
Buat invoice-template.js:
function buildInvoiceHTML({ customerName, orderId, amount, items }) {
const itemRows = items.map(item => `
<tr>
<td style="padding:8px;border-bottom:1px solid #eee">${item.name}</td>
<td style="padding:8px;border-bottom:1px solid #eee;text-align:center">${item.qty}x</td>
<td style="padding:8px;border-bottom:1px solid #eee;text-align:right">Rp${item.price.toLocaleString('id-ID')}</td>
</tr>
`).join('');
return `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px">
<div style="background:#ff801f;padding:20px;border-radius:8px 8px 0 0">
<h1 style="color:#fff;margin:0;font-size:20px">✅ Pembayaran Berhasil</h1>
</div>
<div style="background:#1a1a2e;color:#e0e0e0;padding:20px;border-radius:0 0 8px 8px">
<p style="font-size:16px">Halo <strong>${customerName}</strong>,</p>
<p>Pembayaran kamu untuk pesanan <strong>#${orderId}</strong> telah kami terima.</p>
<table style="width:100%;border-collapse:collapse;margin:20px 0">
<thead>
<tr style="background:#2a2a3e">
<th style="padding:8px;text-align:left;color:#ff801f">Item</th>
<th style="padding:8px;text-align:center;color:#ff801f">Qty</th>
<th style="padding:8px;text-align:right;color:#ff801f">Harga</th>
</tr>
</thead>
<tbody>${itemRows}</tbody>
</table>
<div style="text-align:right;font-size:18px;margin:20px 0;padding:15px;background:#2a2a3e;border-radius:6px">
Total: <strong style="color:#ff801f">Rp${amount.toLocaleString('id-ID')}</strong>
</div>
<p style="color:#888;font-size:12px;margin-top:30px">
Email ini dikirim otomatis oleh sistem kami. Tidak perlu dibalas.<br>
Dikirim melalui <a href="https://mailanvil.com" style="color:#ff801f">MailAnvil</a> — Email API untuk developer Indonesia.
</p>
</div>
</body>
</html>`;
}
Dark theme + aksen oranye MailAnvil (#ff801f). Invoice terlihat profesional meski plain HTML — tanpa framework CSS tambahan.
Langkah 4: Integrasi ke Express Route
Buat server.js:
require('dotenv').config();
const express = require('express');
const { sendPaymentNotification } = require('./mailer');
const app = express();
app.use(express.json());
app.post('/api/payment-webhook', async (req, res) => {
try {
const { email, name, orderId, amount, items } = req.body;
// Validasi minimal
if (!email || !orderId || !amount) {
return res.status(400).json({ error: 'email, orderId, amount wajib diisi' });
}
const result = await sendPaymentNotification({
to: email,
customerName: name,
orderId,
amount,
items
});
console.log(`✅ Email terkirim: ${result.email_id}`);
res.json({ success: true, email_id: result.email_id });
} catch (err) {
console.error('❌ Gagal kirim:', err.message);
// Jangan return 500 mentah — beri pesan Bahasa Indonesia
res.status(502).json({
error: 'Gagal mengirim email notifikasi',
detail: err.message
});
}
});
app.listen(3000, () => {
console.log('🚀 Payment notifier siap di http://localhost:3000');
});
Langkah 5: Test Kirim
Jalankan server:
node server.js
Test dengan curl:
curl -X POST http://localhost:3000/api/payment-webhook \
-H "Content-Type: application/json" \
-d '{
"email": "pelanggan@example.com",
"name": "Budi Santoso",
"orderId": "INV-20260722-0042",
"amount": 127500,
"items": [
{"name": "Nasi Goreng Spesial", "qty": 2, "price": 35000},
{"name": "Es Teh Manis", "qty": 2, "price": 8000},
{"name": "Ayam Goreng Kremes", "qty": 1, "price": 41500}
]
}'
Response sukses:
{"success": true, "email_id": "em_01ARZ3NDEKTSV4RRFFQ69G5FCV"}
Studi Kasus Nyata di Indonesia
1. Food Delivery (GoFood/GrabFood)
Setiap pesanan selesai → trigger webhook → kirim invoice ke email pembeli + email ke merchant. MailAnvil bisa handle 1000+ transaksi per menit tanpa antrian.
2. E-commerce (Tokopedia/Shopee)
Konfirmasi pesanan + update status pengiriman + link tracking — semua via transactional email. Dengan Idempotency-Key, tidak akan ada email terkirim dua kali meski webhook retry.
3. OTP & Verifikasi (Jago, Bank Jago)
Kirim OTP via email sebagai kanal kedua selain SMS. Biaya per email lewat MailAnvil jauh lebih murah dibanding per-SMS — cocok untuk fintech yang kirim ribuan OTP per hari.
Kenapa MailAnvil Bukan SendGrid/Resend
| Fitur | MailAnvil | SendGrid | Resend |
|---|---|---|---|
| Harga | Rp 149rb/bulan (10k email) | $19.95/bulan (~Rp 320rb) | $20/bulan (~Rp 320rb) |
| Pembayaran | QRIS, GoPay, Transfer | Kartu kredit internasional | Kartu kredit internasional |
| Support | Bahasa Indonesia, fast | Bahasa Inggris | Bahasa Inggris |
| MCP-native | ✅ AI agent auto-discovery | ❌ | ❌ |
| Dokumentasi | Bahasa Indonesia + English | English only | English only |
| DKIM auto-setup | ✅ CF DNS users | Manual | Manual |
Untuk startup Indonesia: harga 50% lebih murah, bayar pakai GoPay, support Bahasa Indonesia. Tidak ada alasan pakai yang lain.
Coba Sekarang
- Daftar gratis di mailanvil.com — dapat 500 email/bulan tanpa biaya
- Verifikasi domain (panduan lengkap tersedia di docs.mailanvil.com)
- Copy-paste kode di atas, ganti
fromdengan domain kamu - Kirim email pertama dalam 5 menit
Developer Indonesia bangun untuk Indonesia. MailAnvil — email API pertama yang ngerti kebutuhan developer lokal. 🇮🇩
Tags: #emailAPI #NodeJS #ExpressJS #Indonesia #GoFood #Tokopedia #fintech #transactionalEmail