Kirim Notifikasi Jatuh Tempo Cicilan Otomatis dengan MailAnvil + Node.js
Sektor fintech pembiayaan di Indonesia punya satu masalah klasik: nasabah lupa tanggal jatuh tempo. Hasilnya? Denda menggumpal, nasabah kecewa, tim collections kerja manual menelepon satu per satu. Padahal solusinya sederhana dan murah — email reminder otomatis 3 hari sebelum jatuh tempo dan di hari-H.
Tiga tipe bisnis Indonesia yang langsung merasakan manfaatnya:
- Perusahaan pembiayaan motor (faktur bulanan Rp 750rb–Rp 1,5jt) — pengingat H-3 menurunkan keterlambatan pembayaran signifikan karena nasabah bisa siapkan dana lewat transfer atau gerai retail.
- Platform BNPL e-commerce — notifikasi jatuh tempo tenor 30 hari, plus email tanda terima pelunasan.
- Koperasi digital — angsuran mingguan anggota, sering terlewat karena tidak ada notifikasi terstruktur.
Biayanya kecil: paket Free MailAnvil (3.000 email/bulan, Rp 0) sudah cukup untuk portofolio ±3.000 pinjaman aktif dengan reminder 1x/bulan. Paket Pro Rp 249rb/bulan untuk 50.000 email.
Arsitektur reminder
Cron (node-cron / GitHub Actions / crontab)
→ query D1/PostgreSQL: pinjaman jatuh tempo H-3 & hari-H
→ POST https://api.mailanvil.com/v1/send (Bearer API key)
→ MailAnvil antre via Cloudflare Queue → SES → inbox nasabah
→ webhook status email (delivered/bounce) balik ke sistem Anda
Tidak ada SMTP yang perlu diurus, tidak ada server tambahan. Cron boleh jalan di server aplikasi Anda sendiri.
Langkah 1 — siapkan API key & domain
- Daftar di mailanvil.com, ambil API key dari dashboard.
- Verifikasi domain pengirim (misal
[email protected]) — tambahkan record DKIM yang dashboard berikan, tunggu statusverified. - Catat API key — jangan hardcode, simpan di environment variable.
Langkah 2 — query pinjaman yang mau diingatkan
// reminder-query.js
const { db } = require('./db');
async function getDueLoans(daysAhead) {
return db.all(`
SELECT l.id, l.customer_name, l.customer_email,
l.amount_due, l.due_date, l.installment_no
FROM loans l
WHERE l.status = 'active'
AND l.paid_amount < l.amount_due
AND date(l.due_date) = date('now', '+' || ? || ' days')
`, [daysAhead]);
}
Dipanggil dua kali per hari: getDueLoans(3) (H-3) dan getDueLoans(0) (hari-H). Simpan reminder_sent per (loan_id, tipe reminder) supaya tidak double-send kalau cron kejalan dua kali — idempotency di sisi Anda.
Langkah 3 — kirim via MailAnvil API
// send-reminder.js
const API_KEY = process.env.MAILANVIL_API_KEY;
async function sendReminder(loan, type) {
const isH3 = type === 'h3';
const res = await fetch('https://api.mailanvil.com/v1/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`,
'Idempotency-Key': `reminder-${loan.id}-${type}-${loan.due_date}`,
},
body: JSON.stringify({
from: '[email protected]',
to: [loan.customer_email],
subject: isH3
? `Pengingat: angsuran #${loan.installment_no} jatuh tempo 3 hari lagi`
: `Hari ini jatuh tempo angsuran #${loan.installment_no} Anda`,
html: renderTemplate(loan, isH3), // template HTML + text versi plain
text: renderPlainText(loan, isH3),
}),
});
if (res.status === 202) return true; // queued
if (res.status === 429) return 'rate-limited'; // retry nanti
return false; // 4xx lain → log, jangan retry
}
module.exports = { sendReminder };
Catatan penting:
Idempotency-Keydari MailAnvil memastikan satu reminder yang sama tidak terkirim dobel walau cron replay.- 202 = masuk antre, bukan terkirim. Status akhir per penerima datang lewat webhook — daftarkan URL webhook di dashboard, sistem MailAnvil mengirim event
delivered/bounceddengan signature HMAC-SHA256. - 429 rate-limited: tunggu dan retry. 4xx lain: jangan retry (bisa jadi email invalid atau domain belum verified) — catat untuk ditindaklanjuti tim ops.
Langkah 4 — template email yang gak masuk spam
Pola yang terbukti aman untuk email transaksional ke Gmail Indonesia:
- Subject spesifik: sebut nomor angsuran dan tanggal, bukan "PENTING!!!"
- Rasio teks-ke-HTML seimbang, satu link utama (halaman pembayaran), tanpa link pelacak iklan
- Footer jelas: nama PT + alamat + tombol "menghentikan pengingat?" (meski email transaksional, ini menurunkan penandaan spam)
- Kirim dari subdomain khusus (misal
mail.namafintech.co.id) — kalau reputasi subdomain goyah, domain utama aman
Langkah 5 — cron harian
// cron.js — jalankan 08:00 WIB
const cron = require('node-cron');
const { getDueLoans } = require('./reminder-query');
const { sendReminder } = require('./send-reminder');
cron.schedule('0 8 * * *', async () => {
for (const type of ['h3', 'today']) {
const loans = await getDueLoans(type === 'h3' ? 3 : 0);
for (const loan of loans) {
if (await alreadySent(loan.id, type)) continue;
await sendReminder(loan, type);
await markSent(loan.id, type);
}
}
});
Alternatif tanpa server: GitHub Actions schedule: cron '1 1 * * *' (UTC 01:00 = 08:00 WIB) menjalankan script yang sama. Gratis untuk repo private.
Bonus — escalation flow
Email reminder H-3 dan hari-H adalah kanal paling murah. Kalau webhook melaporkan bounce (email nasabah mati), itu sinyal untuk pindah ke SMS/WhatsApp — jangan biarkan reminder gagal diam-diam. Dengan webhook MailAnvil, Anda tahu dalam hitungan detik mana reminder yang benar-benar sampai.
Mulai sekarang
Daftar gratis di mailanvil.com — 3.000 email/bulan tanpa kartu kredit, bayar pakai QRIS/GoPay kalau butuh lebih, dokumentasi lengkap dalam Bahasa Indonesia, dan MCP-native jadi AI agent Anda bisa langsung integrasi sendiri. Setup pertama (domain + API key + script di atas) selesai dalam satu jam.