pflogsumm ile Günlük Postfix Log Özeti: Teslimat, Reddetme ve Bounce Trendlerini Erken Yakalamak
50 bin satırlık maillog içinde teslimat sorununu gözle aramak, IP itibarınız yandıktan sonra fark etmek demektir. pflogsumm'u tek e-posta değil, bir erken uyarı sistemi olarak kurmayı; deferred, bounced ve rejected sayaçlarını doğru okumayı ve 7 günlük trendden itibar kaybını önceden görmeyi anlatıyoruz.
EvilMail Team28 Temmuz 202611 dk okuma
Bir teslimat sorununu /var/log/mail.log içinde grep ile ararken bulduysanız, muhtemelen geç kalmışsınızdır. Günde 50 bin satır üreten bir mail sunucusunda "bugün bounce arttı mı" sorusunun cevabı ham log içinde bir insana asla görünmez. Görünür hale geldiğinde ise IP itibarınız çoktan aşınmıştır: Google 421-4.7.28 döndürmeye, Spamhaus listelemeye başlamıştır. Sorun logların eksikliği değil, sinyalin gürültüde boğulmasıdır.
pflogsumm tam da bu boşluğu doldurur. Jim Seymour'un yazdığı tek dosyalık bir Perl scripti (Postfix Log Entry Summarizer, hâlâ 1.1.5 sürümünde ve hâlâ çalışıyor), maillog'u okuyup Postfix'in yaşam döngüsündeki her olayı sayaçlara indirger. Ne olduğu kadar ne OLMADIĞI da önemli: pflogsumm gerçek zamanlı bir monitör ya da Alertmanager değildir, günlük postmortem aracıdır. Gücü tekil bir günün rakamında değil, o rakamı her gün arşivleyip delta'sına bakabilmenizde saklıdır.
Ham maillog neden yeterli değil
Postfix bir mesaj için ortalama 4-6 satır log yazar: smtpd
pflogsumm ile Günlük Postfix Log Özeti ve Bounce Trend Raporlama — EvilMail Blog
bağlantıyı alır,
cleanup
başlığı işler,
qmgr
kuyruğa koyar,
smtp
teslim eder. Buna reject satırlarını, retry döngülerini ve TLS handshake'lerini ekleyin.
grep \"status=bounced\"
ile bir günün bounce'larını sayabilirsiniz, tamam; ama bunu her gün elle yapıp önceki güne kıyaslamak, üstelik deferred ile bounced'ı ayırıp reject baskısını ayrı izlemek sürdürülebilir değil. pflogsumm bu işi milisaniyeler içinde yapar ve size okunabilir bir tablo verir.
Tek gerçek bağımlılık Date::Calc Perl modülüdür; paket yöneticisi zaten çeker. Asıl tuzak kurulumda değil, log kaynağında. 2026'da kurulan çoğu sistem varsayılan olarak yalnızca journald'a yazıyor; /var/log/mail.log diye bir dosya hiç oluşmamış olabilir. İki senaryo var.
rsyslog kuruluysa klasik dosyalar yerinde durur ve script'i doğrudan besleyebilirsiniz:
bash
# Debian ailesi
pflogsumm -d yesterday /var/log/mail.log.1
# RHEL ailesi
pflogsumm -d yesterday /var/log/maillog
Yalnızca journald varsa dosya yoktur; journal'ı pipe'lamanız gerekir. Postfix systemd altında [email protected] olarak koşar (instance adı tek tire, yani -):
Burada iki kritik nüans var. Birincisi, --since yesterday --until today sınırlarını iyi seçin; aksi halde iki günün verisini karıştırıp trendi bozarsınız. journalctl'in varsayılan zaman biçimi (Jul 08 00:00:01) klasik syslog formatıyla aynıdır, yani pflogsumm onu sorunsuz ayrıştırır. İkincisi, logrotate. rsyslog kullanıyorsanız gece yarısı mail.log döndürülür ve dünün verisi mail.log.1'e taşınır. Bu yüzden -d yesterday raporu gece yarısından *sonra* koşmalı ve mail.log.1'i hedef almalı; mail.log'a bakarsanız dünün büyük kısmını kaçırırsınız.
Grand Totals'ı okumak: deferred, bounced, rejected aynı şey değil
Raporun kalbi en üstteki Grand Totals bloğudur ve makalenin merkez tezi burada: bir postmaster bu üç sayacı ayırt edemiyorsa kör uçuyor demektir. Her biri Postfix yaşam döngüsünde farklı bir noktaya karşılık gelir.
Sözle özetlersek:
received — cleanup'tan geçip kuyruğa giren mesaj sayısı. Reject edilenler buna dahil değildir.
delivered / forwarded — başarıyla teslim edilen ya da alias/forward ile yönlendirilen mesajlar.
deferred — geçici hata (4xx). Mesaj kuyrukta bekliyor, Postfix tekrar deneyecek. Henüz kaybedilmiş sayılmaz.
bounced — kalıcı hata (5xx). Gönderene NDR (delivery status notification) döndü. Bu mesaj gitti, gönderen kötü bir deneyim yaşadı.
rejected — smtpd mesajı daha kapıda reddetti; kuyruğa hiç girmedi. Bu tamamen inbound bir olaydır, size gelen trafik hakkında bilgi verir, sizin gönderiminiz hakkında değil.
En yaygın kafa karışıklığı deferred ile bounced arasında. deferred = \"henüz olmadı, tekrar denerim\"; bounced = \"olmayacak, pes ettim\". Bir mesaj maximal_queue_lifetime (varsayılan 5 gün) boyunca deferred kalırsa sonunda bounced'a döner. Yani kalıcı yüksek deferred, geciktirilmiş bir bounce dalgasıdır.
Otomasyon: cron ile günlük rapor ve trend arşivi
Elle koşulan bir rapor, koşulmayan bir rapordur. Her gece dünün özetini üretip hem postmaster'a maillemek hem de tarihli bir dosyaya yazmak istiyoruz; çünkü trend, tek günün değil arşivin işidir.
Önce mkdir -p /var/log/pflogsumm yapın. tee sayesinde çıktı hem /var/log/pflogsumm/2026-07-07.txt dosyasına düşer hem de mail'e gider. Bu arşiv olmadan yedi günlük kıyaslama yapamazsınız. journald-only bir sistemde /var/log/mail.log.1 yerine journalctl -u [email protected] --since yesterday --until today | pflogsumm ... kullanın.
Arşivden trend çıkarmak da sizin işiniz. Grand Totals satırlarını CSV'ye kesip küçük bir tablo üretmek yeterli:
bash
for f in /var/log/pflogsumm/2026-*.txt; do
d=$(basename \"$f\" .txt)
rcv=$(grep -m1 'received' \"$f\" | grep -oE '[0-9]+' | head -1)
dlv=$(grep -m1 'delivered' \"$f\" | grep -oE '[0-9]+' | head -1)
dfr=$(grep -m1 'deferred' \"$f\" | grep -oE '[0-9]+' | head -1)
bnc=$(grep -m1 'bounced' \"$f\" | grep -oE '[0-9]+' | head -1)
rej=$(grep -m1 'rejected' \"$f\" | grep -oE '[0-9]+' | head -1)
echo \"$d,$rcv,$dlv,$dfr,$bnc,$rej\"
done
Trendleri okumak: hangi eğri hangi arızayı haber verir
Asıl uzmanlık, tek günün rakamına değil eğrinin şekline bakmaktır. Yüksek hacimli ya da geçici e-posta altyapısında (ki evilmail.pro tam da bu) bounce ve reject trendleri doğrudan gönderim itibarınızı belirler.
İlk üç gün sağlıklı: delivered baskın, ince bir bounce şeridi. Perşembeden itibaren deferred ve bounced segmentleri şişiyor, delivered payı çöküyor. Bu klasik \"IP blocklist'e girdi\" imzasıdır. Sayaç bazında okumak gerekirse:
deferred ani artışı → uzak taraf sizi throttle ediyor, greylisting'e takıldınız ya da bir DNS/bağlantı sorunu var. Raporun Deferrals by reason bölümü sebebi söyler.
bounced ani artışı → liste hijyeniniz bozuldu (spam trap'lere çarpıyorsunuz) ya da IP'niz bir blocklist'e girdi. 5.7.1 blocked ve Google'ın 421 4.7.0 satırları bu tabloda çoğalır.
rejected artışı → iki olasılık. Ya size gelen spam baskısı arttı (genelde iyi haber, filtreniz çalışıyor), ya da yeni bir yanlış yapılandırma kendi meşru kullanıcılarınızı reddediyor (kötü haber). message reject detail bölümünü okuyup hangisi olduğunu ayırt edin.
Kural olarak: outbound bounce spike'ı, inbound reject spike'ından daha acildir. Reject size gelen trafiğe dair; bounce sizin itibarınıza dair. Bounce patlaması ya relay abuse (hesabınız ele geçirildi, spam gönderiliyor) ya da blocklist işaretidir; ikisi de saat meselesidir.
En sık reddetme ve deferral sebepleri
Raporun Deferrals, Bounces ve message reject detail bölümlerinde gerçekte gördüğünüz satırlar ve okuma anahtarı:
451 4.7.1 Greylisting in action, please come back later — greylisting, geçici. Normalde bir sonraki denemede geçer; endişe yok.
550 5.1.1 <x@dom>: Recipient address rejected: User unknown — adres yok. Outbound tarafta görüyorsanız liste hijyeniniz bozuk demektir.
554 5.7.1 Service unavailable; Client host [...] blocked using zen.spamhaus.org — RBL reddi. Inbound'da normaldir; outbound'da IP'niz listede demektir.
450 4.1.8 <x>: Sender address rejected: Domain not found — gönderenin alan adı DNS'te çözülemiyor. Genelde saldırgan/spam; kendi domaininizse SPF/MX kaydınız kırık.
421 4.7.0 [TSS004] ... ya da Google 421-4.7.28 — rate limit / itibar bazlı geciktirme. Karşı taraf \"yavaşla\" diyor. Kalıcıysa itibar sorununuz var.
452 4.2.2 Mailbox full — alıcının kotası dolu. Karşı tarafın sorunu, sizin değil.
Client host rejected: cannot find your hostname — PTR / FCrDNS eksik. Bu sizin altyapı hatanızdır: gönderen IP'nin reverse DNS'i yok ya da forward kaydıyla eşleşmiyor.
Her satırda sorulacak tek soru: bu benim tarafımın hatası mı, karşı tarafın mı, yoksa bir saldırgan mı? PTR eksikliği ve Domain not found sizin tarafınızda çözülür; Mailbox full ve greylist beklemekle geçer; RBL reddini outbound'da görüyorsanız acil delisting başvurusu gerekir.
Faydalı bayraklar ve rapor sıkılaştırma
pflogsumm'un varsayılan çıktısı yoğun bir sunucuda kalabalıklaşabilir; günlük postmaster maili için sinyali sıkıştırın, forensik için genişletin. Bayrakların hem --alt_cizgi hem --alt-cizgi yazımı çalışır:
-d today|yesterday — gün filtresi. Günlük cron için yesterday.
--problems_first — deferred/bounce/reject bölümlerini raporun başına al. Postmaster maili için şart; önce sorunu görürsünüz.
-q — boş raporların başlıklarını bastır (uyarı/fatal/master başlıkları yine basılır). Maili kısaltır.
-u N / -h N — top N kullanıcı (gönderen/alıcı) ve top N host/domain. -u 10 iyi bir varsayılan; 0 kapatır.
--detail N — tüm detay bölümlerini N satırla sınırlar; --detail 0 tüm detayı keser. Maili kısa tutmanın en temiz yolu.
--zero_fill — boş saatleri 0 ile doldur. Saatlik trend kesiti için şart; yoksa saat eksenleri kayar.
--iso_date_time — rapordaki tarih/saat başlıklarını ISO 8601 (YYYY-MM-DD, HH:MM) biçiminde yazar; arşiv dosyalarını makineyle işlemeyi kolaylaştırır.
--smtpd_stats, --rej_add_from — smtpd bağlantı istatistikleri ve reject listelerine gönderen adresini ekleme. Manuel forensikte açın.
-e / --verbose_msg_detail — per-message izleme. Sadece tek bir olayı kovalarken kullanın; günlük mailde asla.
Günlük mail için pratik kombinasyon: --problems_first -q --detail 10 -u 10 --zero_fill --iso_date_time. Bir olayı kovalarken: -e --verbose_msg_detail --rej_add_from --smtpd_stats.
Pratik kontrol listesi
/etc/cron.d/pflogsumm kuruldu, gece 00:05'te -d yesterday koşuyor.