Mail sunucusu yönetiminin en can sıkıcı ama bir o kadar da kritik konularından biri bounce mail yönetimidir. Bir sabah kalktığında sunucu loglarının binlerce “delivery failed” mesajıyla dolup taştığını görmen, ya da müşterinin “maillerimiz gitmiyor” diye araması… Bu durumları yaşamadan önce Postfix’in bounce mekanizmasını anlamak ve doğru yapılandırmak hayat kurtarır.
Bounce Mail Nedir ve Neden Önemlidir?
Bounce mail, teslim edilemeyen bir e-postanın gönderene iade edilmesiyle oluşan bildirim mesajıdır. İki temel türü vardır:
- Hard bounce: Kalıcı hata. Adres yok, domain yok, sunucu erişilemez gibi durumlar. SMTP 5xx hata kodları.
- Soft bounce: Geçici hata. Posta kutusu dolu, sunucu geçici olarak yanıt vermiyor gibi durumlar. SMTP 4xx hata kodları.
Postfix bu iki türü farklı şekilde ele alır. Hard bounce durumunda mesaj hemen gönderene iade edilir. Soft bounce durumunda ise Postfix mesajı kuyruğa alır ve belirli aralıklarla yeniden denemeye çalışır.
Bounce yönetimini ihmal edersen şu sorunlarla karşılaşırsın:
- Sunucu disk alanı deferred kuyrukla dolup taşar
- IP itibarın düşer, meşru mailerin spam klasörüne düşmeye başlar
- Backscatter saldırılarına açık hale gelirsin
- Sistemin gereksiz yük altında kalır
Postfix Bounce Mekanizmasının Çalışma Prensibi
Postfix, teslim edilemeyen mailleri yönetmek için birkaç dahili servis kullanır. bounce, defer ve trace servisleri bu işin omurgasını oluşturur.
Bir mail teslim edilemediğinde şu süreç işler:
- Postfix teslim denemesinde başarısız olur
bounceservisi bir bildirim mesajı oluşturur- Bu bildirim orijinal mailin “Return-Path” veya “Sender” adresine gönderilir
- Orijinal mesaj silinir veya kuyruğa alınır
Kuyruk dizinlerini şu komutla inceleyebilirsin:
ls -la /var/spool/postfix/
# deferred/ - geçici hata alan mailler
# bounce/ - bounce bildirimleri
# active/ - aktif işlemde olan mailler
# incoming/ - yeni gelen mailler
Postfix Konfigürasyon Dosyasında Bounce Ayarları
/etc/postfix/main.cf dosyasında bounce davranışını kontrol eden parametreler şunlardır:
- bounce_notice_recipient: Bounce bildirimlerinin kopyasının gönderileceği adres
- bounce_size_limit: Bounce mesajına eklenecek orijinal mailin maksimum boyutu (byte)
- bounce_queue_lifetime: Bounce mesajlarının kuyrukta kalma süresi
- maximal_queue_lifetime: Geçici hata alan maillerin kuyrukta kalma süresi
- minimal_backoff_time: Başarısız teslimat sonrası ilk bekleme süresi
- maximal_backoff_time: Başarısız teslimat denemeleri arasındaki maksimum bekleme süresi
- delay_warning_time: Gecikmiş mail için gönderene uyarı gönderilene kadar geçecek süre
Temel bir yapılandırma örneği:
# /etc/postfix/main.cf
# Bounce bildirimlerini postmaster'a kopyala
bounce_notice_recipient = [email protected]
2bounce_notice_recipient = [email protected]
# Geçici hata alan mailler için kuyrukta kalma süresi (varsayılan 5 gün)
maximal_queue_lifetime = 2d
# Bounce mesajları için kuyrukta kalma süresi
bounce_queue_lifetime = 1d
# Gecikme uyarısı gönderme süresi (0 = uyarı gönderme)
delay_warning_time = 4h
# İlk yeniden deneme süresi
minimal_backoff_time = 300s
# Maksimum yeniden deneme aralığı
maximal_backoff_time = 4000s
# Bounce mesajına eklenecek orijinal mail boyutu
bounce_size_limit = 50000
Değişiklikler sonrası Postfix’i yeniden yükle:
postfix reload
# veya
systemctl reload postfix
Gerçek Dünya Senaryosu 1: Toplu Mail Gönderiminde Bounce Yönetimi
Diyelim ki bir e-ticaret firmasının sistem yöneticisisin. Pazarlama ekibi 50.000 kişilik bir listeye kampanya maili gönderdi ve sabah 3.000 bounce mesajı kuyrukta birikiyor. Bu durumda ne yaparsın?
Önce mevcut durumu değerlendir:
# Kuyruktaki mail sayısını öğren
postqueue -p | tail -1
# Sadece bounce/deferred sayısını gör
postqueue -p | grep -c "^[A-F0-9]"
# Belirli bir hataya göre filtrele
postqueue -p | grep "User unknown"
# Kuyruk durumunun detaylı özeti
qshape deferred
Sonra bounce sebeplerini analiz et:
# Mail loglarında bounce sebeplerini say ve sırala
grep "status=bounced" /var/log/mail.log |
grep -oP "said: d+ .*?(?=()" |
sort | uniq -c | sort -rn | head -20
“User unknown” hatası alan mailleri kuyruğundan temizle:
# Kuyruktaki "user unknown" hatalarını temizle
postqueue -p | grep -B1 "User unknown" |
grep "^[A-F0-9]" |
awk '{print $1}' | tr -d '*!' |
while read id; do postsuper -d $id; done
Bounce Mail Loglarını Düzgün Analiz Etmek
Postfix log analizi bounce sorunlarını çözmede kritik öneme sahiptir. /var/log/mail.log veya /var/log/maillog dosyasını etkili kullanmak gerekir.
# Bugünkü tüm bounce olaylarını listele
grep "$(date '+%b %e')" /var/log/mail.log | grep "status=bounced"
# Hangi domain'lere mail gönderilemiyor?
grep "status=bounced" /var/log/mail.log |
grep -oP "to=<[^>]+>" |
grep -oP "@[^>]+" |
sort | uniq -c | sort -rn | head -10
# Son 1 saatteki bounce istatistikleri
awk -v d="$(date -d '1 hour ago' '+%b %e %H')"
'$0 > d && /status=bounced/' /var/log/mail.log | wc -l
# Bounce loglarını gerçek zamanlı izle
tail -f /var/log/mail.log | grep --line-buffered "bounced|deferred"
Backscatter Koruması
Backscatter, sahte “From” adresiyle gönderilen spam maillerin bounce bildirimlerinin masum kullanıcılara ulaşması durumudur. Postfix sunucun backscatter kaynağı haline gelirse IP itibarın ciddi zarar görür.
Backscatter’ı önlemenin en etkili yolu Sender Address Verification ve VERP kullanmaktır. Ancak en pratik çözüm bounce mesajlarını yalnızca bilinen geçerli adresler için göndermektir:
# /etc/postfix/main.cf
# Bilinmeyen alıcılar için "reject" kullan, bu backscatter'ı keser
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_unknown_recipient_domain,
reject_non_fqdn_recipient
# Null sender ile gelen mailleri kısıtla (bounce saldırıları için kullanılır)
smtpd_sender_restrictions =
reject_unknown_sender_domain
# Boş envelope sender'dan gelen maillerde hız sınırı
smtpd_client_message_rate_limit = 100
anvil_rate_time_unit = 60s
DSN (Delivery Status Notification) mesajlarını kontrol altına almak için:
# /etc/postfix/main.cf
# Bounce mesajlarında orijinal mailin ne kadarını ekle
bounce_size_limit = 0
# Bounce bildirimlerini tamamen kapat (dikkatli kullan!)
# notify_classes = resource, software
# Bu ayar sadece postmaster bildirimlerini etkiler
# Verilen bir adresten gelen bounce döngülerini engelle
# Return-Path: <> olan mailler için header kontrolü
header_checks = regexp:/etc/postfix/header_checks
/etc/postfix/header_checks dosyasına şunları ekle:
# Bounce döngülerini engelle
/^From:.*MAILER-DAEMON/i DISCARD
/^Subject:.*Auto-Reply/i DISCARD
/^Auto-Submitted:s*auto-replied/i DISCARD
Gerçek Dünya Senaryosu 2: Deferred Kuyruk Şişmesi
Bir gece monitoring sistemin alarm veriyor. /var/spool/postfix dizini disk alanının %90’ını doldurmuş. Deferred kuyruğa bakıyorsun ve 15.000 mail birikiyor. Hedef sunucu geçici olarak erişilemez durumda.
# Kaç mail deferred kuyruğunda?
ls /var/spool/postfix/deferred/ | wc -l
# Hangi hedef sunucuya gönderilemiyor?
postqueue -p | grep "deferred" |
grep -oP "relay=S+" | sort | uniq -c | sort -rn
# Belirli bir hedefe giden tüm mailleri zorla dene
postqueue -s gmail.com
# Tüm deferred mailleri hemen yeniden dene
postqueue -f
# Belirli bir domain'e giden deferred mailleri sil
postqueue -p | grep "@hedef-domain.com" |
awk '{print $1}' | tr -d '*!' |
while read id; do
[ -n "$id" ] && postsuper -d "$id"
done
Eğer sorun tekrar ediyorsa ve hedef sunucu sürekli erişilemez durumda kalıyorsa, bu domain için kalıcı yönlendirme veya hata yönetimi yapılandırabilirsin:
# /etc/postfix/transport dosyasına ekle
sorunlu-domain.com error:Domain geçici olarak hizmet dışı
# transport.db'yi güncelle
postmap /etc/postfix/transport
# main.cf'e ekle
transport_maps = hash:/etc/postfix/transport
Bounce Bildirimleri için Özel Script
Bounce raporlarını düzenli olarak takip etmek için basit bir bash script yazalım:
#!/bin/bash
# /usr/local/bin/bounce-report.sh
# Günlük bounce raporu oluşturur ve mail gönderir
LOGFILE="/var/log/mail.log"
REPORT_TO="[email protected]"
DATE=$(date '+%Y-%m-%d')
YESTERDAY=$(date -d yesterday '+%b %e')
TMPFILE=$(mktemp)
echo "=== Postfix Bounce Raporu: $DATE ===" > $TMPFILE
echo "" >> $TMPFILE
# Toplam bounce sayısı
TOTAL=$(grep "$YESTERDAY" $LOGFILE | grep -c "status=bounced")
DEFERRED=$(grep "$YESTERDAY" $LOGFILE | grep -c "status=deferred")
SENT=$(grep "$YESTERDAY" $LOGFILE | grep -c "status=sent")
echo "Ozet:" >> $TMPFILE
echo " Basarili: $SENT" >> $TMPFILE
echo " Bounce: $TOTAL" >> $TMPFILE
echo " Deferred: $DEFERRED" >> $TMPFILE
echo "" >> $TMPFILE
# En cok bounce alan domainler
echo "En Cok Bounce Alan Domainler (Top 10):" >> $TMPFILE
grep "$YESTERDAY" $LOGFILE | grep "status=bounced" |
grep -oP "to=<[^>]+>" | grep -oP "@[^>]+" |
sort | uniq -c | sort -rn | head -10 >> $TMPFILE
echo "" >> $TMPFILE
# Bounce sebepleri
echo "Bounce Sebepleri:" >> $TMPFILE
grep "$YESTERDAY" $LOGFILE | grep "status=bounced" |
grep -oP "said: d+ d.d.d [^(]+" |
sort | uniq -c | sort -rn | head -10 >> $TMPFILE
# Raporu gönder
cat $TMPFILE | mail -s "Postfix Bounce Raporu - $DATE" $REPORT_TO
rm -f $TMPFILE
echo "Bounce raporu gönderildi: $REPORT_TO"
Script’i çalıştırılabilir yap ve cron’a ekle:
chmod +x /usr/local/bin/bounce-report.sh
# Her gün sabah 07:00'de rapor gönder
echo "0 7 * * * root /usr/local/bin/bounce-report.sh" > /etc/cron.d/bounce-report
Bounce Adreslerini Temizleme (Suppression List)
Sürekli bounce veren adresleri otomatik olarak bir suppression listesine almak, tekrar tekrar gönderim denemesini engeller ve IP itibarını korur. Postfix’te bu işlemi access tablosuyla yapabilirsin:
# /etc/postfix/recipient_access dosyası oluştur
# Buraya sürekli bounce veren adresleri ekle
geç[email protected] REJECT Adres artık aktif değil
baş[email protected] REJECT Permanent failure
# Tüm geçersiz adreslerin olduğu bir domain varsa
eski-domain.com REJECT Domain artık aktif değil
# Hash veritabanı oluştur
postmap /etc/postfix/recipient_access
# main.cf'e ekle
smtpd_recipient_restrictions =
check_recipient_access hash:/etc/postfix/recipient_access,
permit_mynetworks,
reject_unauth_destination
Bounce loglarından otomatik suppression listesi oluşturan küçük bir script:
#!/bin/bash
# Bounce loglarından sürekli hata veren adresleri çıkar
# 5xx hatası 3'ten fazla olan adresleri listele
grep "status=bounced" /var/log/mail.log |
grep -oP "to=<K[^>]+" |
sort | uniq -c | sort -rn |
awk '$1 >= 3 {print $2 "t REJECT Permanent bounce"}' |
tee -a /etc/postfix/recipient_access
# Veritabanını güncelle
postmap /etc/postfix/recipient_access
postfix reload
DSN ve Bounce Mesaj Formatını Özelleştirme
Postfix, bounce mesajlarının içeriğini özelleştirme imkanı sunar. Bu özellik özellikle kurumsal ortamlarda kullanışlıdır.
# /etc/postfix/main.cf
bounce_template_file = /etc/postfix/bounce.cf
/etc/postfix/bounce.cf dosyasını oluştur:
# Postfix bounce mesaj şablonu
failure_notice_sender = MAILER-DAEMON
failure_notice_recipients = $bounce_notice_recipient
failure_notice_subject = Undelivered Mail Returned to Sender
# Gönderene giden bounce mesajı
failure_notice_text = <<EOF
Gönderdiğiniz mail teslim edilemedi.
Teknik destek için: [email protected]
Referans numarası: ${queue_id}
Hata detayı:
${recipients}
EOF
Şablonu doğrula:
postconf -b /etc/postfix/bounce.cf
Monitoring ve Alerting Entegrasyonu
Bounce oranını sürekli izlemek için Postfix loglarından metrik çıkaran bir araç kullanmak gerekir. Nagios/Zabbix olmayan ortamlarda basit bir threshold kontrolü yeterli olur:
#!/bin/bash
# /usr/local/bin/check-bounce-rate.sh
# Bounce oranı %10'u geçerse uyarı gönderir
THRESHOLD=10
PERIOD=3600 # Son 1 saat
ALERT_MAIL="[email protected]"
SENT=$(grep "status=sent|status=bounced" /var/log/mail.log |
awk -v t=$(date -d "$PERIOD seconds ago" +%s)
'{cmd="date -d ""$1" "$2" "$3"" +%s"; cmd | getline ts; close(cmd); if(ts>t) print}' |
grep -c "status=sent")
BOUNCED=$(grep "status=bounced" /var/log/mail.log |
awk -v t=$(date -d "$PERIOD seconds ago" +%s)
'{cmd="date -d ""$1" "$2" "$3"" +%s"; cmd | getline ts; close(cmd); if(ts>t) print}' |
wc -l)
TOTAL=$((SENT + BOUNCED))
if [ $TOTAL -gt 0 ]; then
RATE=$((BOUNCED * 100 / TOTAL))
if [ $RATE -gt $THRESHOLD ]; then
echo "UYARI: Bounce oranı %$RATE (Son 1 saat: $BOUNCED bounce / $TOTAL toplam)" |
mail -s "Postfix Bounce Rate ALERT: %$RATE" $ALERT_MAIL
fi
fi
Sıkça Yapılan Hatalar
Postfix bounce yönetiminde sysadminlerin sıkça düştüğü hatalar ve çözümleri:
- maximal_queue_lifetime’ı çok yüksek tutmak: Varsayılan 5 gün genellikle fazla. 2 gün çoğu senaryo için yeterli. Disk alanı gereksiz yere dolar.
- bounce_notice_recipient ayarlamamak: Bounce bildirimlerinin nereye gittiğini bilmemek körlüktür. Mutlaka geçerli bir adres ayarla.
- Deferred kuyruku hiç temizlememek: Aylarca deferred kuyruğunda bekleyen mailler sunucu performansını etkiler. Haftalık temizlik rutini oluştur.
- Backscatter’a karşı önlem almamak: Özellikle yüksek trafikli sunucularda bu kritik bir güvenlik açığıdır.
- Log rotasyonu ile bounce analizini senkronize etmemek: Log rotate olduktan sonra analiz script’lerin eski dosyayı okuyamadığı için hatalı raporlar oluşur.
Sonuç
Postfix bounce yönetimi, mail sunucusu sağlığının temel göstergelerinden biridir. Bounce oranını düşük tutmak, IP itibarını korumak ve kuyruğu temiz tutmak birbirini doğrudan etkileyen üç unsurdur. Bu yazıda anlattığımız yapılandırmaları adım adım uygularsan:
- Gereksiz retry denemeleri azalır, sunucu yükü düşer
- Disk alanı verimsiz kullanılmaz
- IP bloklanma riski minimize edilir
- Sorunlar erken tespit edilir
En önemli tavsiyem şu: Bounce loglarını düzenli oku. Bir sunucunun ne kadar sağlıklı çalıştığını anlamak için mail logları altın madenidir. Günlük bir bounce raporu e-postası, sabah kahveni içerken beş dakikada sorunları fark etmeni sağlar. Monitoring olmayan bir mail sunucusu, gözetimsiz bırakılmış bir yangın tüpü gibidir; bir gün ihtiyaç duyduğunda boş çıkabilir.