Kendi Postfix Transaksiyonel Relay'inizi Kurun: SMTP API'lerine Kontrollü Bir Alternatif
SendGrid, Postmark ve SES tek başarısızlık noktasıdır: sürpriz fiyat sıçraması, "hesabınız askıya alındı" e-postası ve kontrol dışı bir çıkış yolu. Bu rehber, kritik akışlarınız için sağlayıcıdan bağımsız, denetlenebilir bir Postfix transaksiyonel relay'ini adım adım kurar — API'yi atmadan, yanına failover olarak koyarak.
EvilMail Team1 Ağustos 202613 dk okuma
Cuma gecesi 23:40. SES hesabınız "unusual sending pattern" gerekçesiyle sandbox moduna düşürüldü ve tam o an bir kullanıcı şifresini sıfırlamaya çalışıyor. E-posta gitmiyor. Destek ticket'ınız pazartesiye kadar sırada. Sorun SES'in kötü olması değil; SES iyi bir servistir. Sorun, uygulamanızın en kritik akışının çıkış kontrolünün tamamen üçüncü bir tarafta olması.
Bu yazı, submission-only mimariyle tam bir Postfix transaksiyonel relay kurmayı ve onu mevcut API sağlayıcınızla yan yana çalıştırmayı gösterir: DKIM/SPF/DMARC, zorunlu TLS, bounce/FBL işleme ve sağlayıcı failover'ı dahil. Amaç API'yi çöpe atmak değil; şifre sıfırlama, OTP ve ödeme onayı gibi "asla düşmemeli" akışlarınız için sizin kontrolünüzde, denetlenebilir ikinci bir çıkış yolu inşa etmek.
Ne zaman self-host, ne zaman API — dürüst karar
Self-host her derde deva değil; kabul ettiğiniz trade-off'ları bilerek yapın. Sınırları net çizelim:
Self-host mantıklı: Günde 10.000 altında transaksiyonel mesaj, elinizde statik IPv4 ve PTR kaydını düzenleme yetkisi, çıkış port 25 açık ya da açtırılabiliyor, KVKK/GDPR gereği e-posta içeriğinin üçüncü tarafa gitmemesi bir gereksinim.
API mantıklı:
Pazarlama patlamaları (kampanya anında 500 bin mesaj), IP warm-up eforuna girmek istemeyen küçük ekip, saatlik dalgalı hacim, birden çok bölgeye coğrafi dağıtım ihtiyacı.
Maliyet eğrisi çoğu kişinin sandığı yerde kırılmaz. SES ~$0,10/1000 e-posta ile fiilen bedava sayılır; Postmark ~$1,25/1000 ile 12 kat pahalı ama daha temiz bir reputation havuzu ve daha iyi bir bounce API'si sunar. Self-host tarafında sabit maliyet komik: $5-20/ay VPS. Ama gerçek maliyet parada değil — IP reputation'ı kurmak ve korumak için harcayacağınız mühendislik zamanında. Kırılma noktası hacme değil, o zamanı kimin ödediğine bağlı.
Net tavsiye: hacminiz ne olursa olsun, OTP ve şifre sıfırlama gibi akışlar için hibrit gidin. Primary olarak kendi relay'iniz, timeout/5xx durumunda API'ye düşen bir fallback. Böylece ne vendor lock-in'e ne de tek bir IP'nin kara listeye düşmesine tam bağımlı kalırsınız.
Relay çalışmadan önce hazır olması gereken temel
E-posta reddedilmelerinin çoğu Postfix'e hiç gelmeden, DNS ve ağ katmanında olur. Sırasıyla:
Reverse DNS (PTR) + FCrDNS. IP'nizin ters kaydı hostname'inize dönmeli, hostname de aynı IP'ye. Bu eşleşme (forward-confirmed reverse DNS) olmadan Gmail ve Outlook bağlantıyı 5xx ile keser.
bash
# Ters kayıt hostname döndürmeli
dig -x 203.0.113.10 +short # → mail.evilmail.pro.
# İleri kayıt aynı IP'ye dönmeli
dig +short mail.evilmail.pro # → 203.0.113.10
PTR kaydını hosting paneliniz ya da VPS sağlayıcınız üzerinden ayarlarsınız — kendi DNS zone'unuzda değil.
Çıkış port 25. Hetzner, DigitalOcean ve AWS varsayılan olarak giden 25'i bloklar; açtırmak için destek ticket'ı gerekir. Test edin:
Temiz IP. Kurulumdan önce IP'nizi Spamhaus (zen.spamhaus.org) ve Barracuda listelerinde kontrol edin. İkinci el bir VPS IP'si zaten yanmış olabilir; öyleyse sağlayıcıdan temiz IP isteyin.
Postfix'i submission-only relay olarak kurmak
Burada klasik "tam mail sunucusu" kurmuyoruz. Kutu tek iş yapacak: uygulamadan localhost üzerinden mesaj alıp dışarıya, alıcı MX'lerine teslim etmek. Gelen kutusu yok, POP/IMAP yok, açık relay yok. main.cf'in kritik satırları:
ini
myhostname = mail.evilmail.pro
mydomain = evilmail.pro
myorigin = $mydomain
# Sadece localhost'tan mesaj kabul et — app aynı hostta
inet_interfaces = loopback-only
mynetworks = 127.0.0.0/8 [::1]/128
# Giden TLS: alıcı destekliyorsa şifrele (opportunistic)
smtp_tls_security_level = may
smtp_tls_mandatory_ciphers = high
smtp_tls_loglevel = 1
smtp_tls_note_starttls_offer = yes
# Warm-up: ilk günler kasıtlı yavaş
default_destination_rate_delay = 1s
smtp_destination_concurrency_limit = 2
# İç hostname/IP sızıntısını header'dan temizle
smtp_header_checks = regexp:/etc/postfix/header_checks
inet_interfaces = loopback-only kutunuzu dışarıdan gelen bağlantılara tamamen kapatır — bu bir relay, gelen sunucu değil. default_destination_rate_delay = 1s ve concurrency_limit = 2, taze IP'de Gmail'e saniyede yüzlerce mesaj yağdırıp anında graylisting yemeyi engeller; reputation oturdukça bu değerleri gevşetirsiniz.
Header sızıntısını /etc/postfix/header_checks ile kapatın:
Regexp map postmap gerektirmeden doğrudan okunur; değişiklikten sonra postfix reload.
DNS: relay'inizi "yasal" yapan kayıtlar
Üç imza kaydı olmadan modern hiçbir alıcı sizi ciddiye almaz. Sırasıyla SPF, DKIM, DMARC — ve TLS downgrade'e karşı MTA-STS.
SPF (apex TXT). Yalnızca relay IP'nizi yetkilendirin:
evilmail.pro. TXT "v=spf1 ip4:203.0.113.10 -all"
Fallback için API sağlayıcınızı da eklerseniz (include:amazonses.com gibi) toplam DNS lookup 10'u geçemez, yoksa SPF permerror verir ve tüm doğrulama çöker.
adkim=s; aspf=s sıkı hizalama demektir — imzalayan alan ile From alanı birebir eşleşmeli. Emin olana kadar p=none kalın; hazır olduğunuzda quarantine, sonra reject.
MTA-STS + TLS-RPT. Aktif bir saldırganın STARTTLS'i düşürüp trafiği düz metne çevirmesini engeller:
Bu doğrulama zinciri kafada dağınık durur; sırayı bir kez görün, hangi kaydın hangi kapıyı açtığı netleşsin:
Bounce, feedback loop ve suppression — API'nin sizin için yaptığı iş
Self-host'ta gerçekten kaybettiğiniz şey burasıdır, DNS değil. Postmark sizin için hard bounce'ları suppression listesine yazar, complaint'leri toplar, geri gönderimi keser. Kendi relay'inizde bunu kurmazsanız reputation'ınız birkaç günde ölür.
VERP ile bounce eşleştirme. Envelope sender'a mesaj kimliğini gömerek hangi alıcının bounce ettiğini kesin bilirsiniz. Postfix'te bounce'lar bir pseudo-mailbox'a düşer; bir script hard bounce'ları (5.1.1 user unknown) ayrıştırıp kalıcı suppression tablosuna yazar.
Suppression enforcement. Postfix, bilinen ölü adreslere teslimatı denemeden reddetsin:
/etc/postfix/suppression içine [email protected] REJECT 550 suppressed yazıp postmap /etc/postfix/suppression çalıştırırsınız. Sıralama önemli: check_recipient_accesspermit_mynetworks'ten önce gelir, yoksa localhost'tan gelen her mesaj suppression'a bakılmadan geçer. Böylece hard bounce almış adrese ikinci kez göndererek reputation'ı yakmazsınız.
Feedback loop kaydı. Google Postmaster Tools'a domain'i ekleyin, Microsoft SNDS'e IP'yi kaydettirin, Yahoo CFL'ye abone olun. Eşikler acımasız: Gmail Postmaster'da spam rate hedefi 0,1%; 0,3% üstünde teslimat çöker. Kıyas olsun diye: SES bile hard bounce >5% ya da complaint >0,1% olduğunda hesabı askıya alır. Self-host'ta bu sınırları hiçbir sağlayıcı sizin adınıza zorlamaz — kendiniz izlersiniz.
Hibrit mimari: relay + API failover
Uygulama katmanında iki transport tanımlarsınız. Primary localhost Postfix; hata ya da timeout'ta secondary API transport'una düşülür. evilmail'de mailer src/lib/mailer.ts içinde yaşar ve SMTP konfigürasyonunu settings DB + Redis cache üzerinden okur; aynı desen:
Warm-up döneminde bu ikiliyi bir oran kapısıyla kullanın: ilk hafta trafiğin %20'sini kendi relay'inizden, %80'ini API'den geçirin; reputation oturdukça self tarafını kademeli artırın. Fallback'e düşen mesajları bir dead-letter kaydına yazın ki sessizce kaybolan bir akış olmasın.
İzleme ve teslim edilebilirlik doğrulama
Kurdunuz; şimdi kanıtlayın. Uçtan uca test için swaks:
Ve tek sayısal doğruluk kaynağı olarak mail-tester.com — 10/10 altında bir skorla asla canlıya çıkmayın. Google Postmaster Tools'ta domain ve IP reputation grafiklerini haftalık izleyin. Alarm eşikleri: deferred kuyruk 100'ü geçerse ya da bounce rate 2%'yi aşarsa haber alın.
Yayın öncesi kontrol listesi
[ ] dig -x PTR kaydı hostname'e dönüyor, ileri kayıt aynı IP'ye — FCrDNS eşleşiyor
[ ] Çıkış port 25 açık (nc -zv gmail-smtp-in.l.google.com 25)
[ ] IP Spamhaus/Barracuda'da temiz
[ ] SPF, DKIM ve DMARC mail-tester'da geçiyor, skor 10/10