Supabase Edge Functions ile Otomatik E-posta Bildirimi Kurma
Sipariş gelince müdüre, stok düşünce satın almacıya otomatik bildirim gönderen bir sistem nasıl kurulur? PostgreSQL trigger + e-posta kuyruğu + Edge Function rehberi.
Sorun: Önemli Olayları Kimse Fark Etmiyor
Kurumsal bir uygulamada sürekli bir şeyler oluyor:
- Yeni sipariş geldi → Şube müdürü bilmeli
- Stok kritik seviyeye düştü → Satın almacı bilmeli
- Görev atandı → Atanan kişi bilmeli
Ama kimse sürekli ekran başında oturup kontrol edemez. Otomatik bildirim lazım.
Çözüm: 3 Katmanlı Bildirim Sistemi
1. Veritabanında bir şey değişir (sipariş eklenir)
↓
2. Trigger otomatik tetiklenir → e-posta kuyruğuna ekler
↓
3. Edge Function kuyruktaki e-postaları gönderir
Neden doğrudan e-posta göndermiyoruz? Çünkü:
- Hata olursa tekrar deneyebilmek istiyoruz (retry)
- Aynı bildirimi iki kez göndermek istemiyoruz
- Gönderim geçmişini tutmak istiyoruz
1. E-posta Kuyruk Tablosu
Gönderilecek e-postalar burada sıra bekler:
CREATE TABLE email_queue (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
recipient_email TEXT NOT NULL,
subject TEXT NOT NULL,
html_body TEXT NOT NULL,
event_type TEXT NOT NULL, -- 'siparis_olusturuldu', 'stok_kritik' vb.
status TEXT DEFAULT 'pending', -- pending, sent, failed
retry_count INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
sent_at TIMESTAMPTZ,
-- Aynı olay için aynı kişiye 1 e-posta
UNIQUE(event_type, source_id, recipient_email)
);
2. Trigger: Olay Olunca Kuyruğa Ekle
Siparişler tablosuna yeni kayıt eklendiğinde otomatik tetiklenir:
CREATE FUNCTION bildirim_yeni_siparis()
RETURNS TRIGGER AS $$
BEGIN
-- Şube müdürünün e-postasını bul
-- Kuyruğa ekle
INSERT INTO email_queue (
recipient_email,
subject,
html_body,
event_type
) VALUES (
mudur_email,
'Yeni Sipariş: ' || NEW.siparis_no,
'<h2>Yeni sipariş oluşturuldu</h2>
<p>Sipariş No: ' || NEW.siparis_no || '</p>
<p>Toplam: ' || NEW.toplam || ' TL</p>',
'siparis_olusturuldu'
) ON CONFLICT DO NOTHING; -- Aynı bildirimi tekrar ekleme
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Tabloya bağla
CREATE TRIGGER trg_yeni_siparis
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION bildirim_yeni_siparis();
Artık sipariş eklenince otomatik olarak e-posta kuyruğa düşüyor.
3. Edge Function: Kuyruktakileri Gönder
Supabase Edge Function, kuyruktaki bekleyen e-postaları alıp gönderir:
// supabase/functions/send-email/index.ts
serve(async () => {
// Bekleyen e-postaları al
const { data: bekleyenler } = await supabase
.from('email_queue')
.select('*')
.eq('status', 'pending')
.limit(10);
for (const email of bekleyenler) {
try {
// Resend API ile gönder
await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${RESEND_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'Bildirim <bildirim@firma.com>',
to: email.recipient_email,
subject: email.subject,
html: email.html_body,
}),
});
// Başarılı → durumu güncelle
await supabase
.from('email_queue')
.update({ status: 'sent', sent_at: new Date().toISOString() })
.eq('id', email.id);
} catch (hata) {
// Başarısız → retry sayısını artır
await supabase
.from('email_queue')
.update({
retry_count: email.retry_count + 1,
status: email.retry_count >= 2 ? 'failed' : 'pending'
})
.eq('id', email.id);
}
}
});
Otomatik Tetikleme
Edge Function’ı düzenli aralıklarla çalıştırmak için:
-- Her 5 dakikada bir çalıştır
SELECT cron.schedule(
'eposta-gonder',
'*/5 * * * *', -- Her 5 dk
$$ SELECT net.http_post(
url := 'https://proje.supabase.co/functions/v1/send-email',
headers := '{"Authorization": "Bearer SERVICE_KEY"}'
); $$
);
Sonuç: Ne Kazanırsınız?
Sipariş geldi → 5 dakika içinde müdüre e-posta
Stok düştü → Satın almacıya otomatik uyarı
Görev atandı → Kişiye bildirim
Hiçbir şey unutulmaz. Kimse sürekli ekran başında olmak zorunda kalmaz.
Bu Yaklaşım Temel Senaryolar İçin Yeter
3-5 farklı bildirim tipi için bu yapı mükemmel çalışır. Ama 15+ modül, 9 farklı rol, şube bazlı filtreler ve uygulama içi gerçek zamanlı bildirimler devreye girince mimari derinleşir.
Biz bu sistemi 30+ tablo üzerinde çalıştırıyoruz. İhtiyacınız olursa deneyimimizden faydalanabilirsiniz.
Bu yazı AstaFlow Case Study serisinin bir parçasıdır.