Yüksek Mail Kuyruğu: Sebep Analizi ve Önleme
Mail sunucusu yönetimi, sysadmin hayatının en stresli alanlarından biri. Sabah 07:00’de telefonun çalıyor, “mailler gitmiyor” şikayetiyle uyanıyorsun ve Postfix kuyruğuna baktığında binlerce mesajın orada birikmiş beklediğini görüyorsun. İşte tam bu noktada paniklemek yerine sistematik bir yaklaşımla hareket etmek gerekiyor. Bu yazıda yüksek mail kuyruğu sorununu derinlemesine inceleyeceğiz, sebeplerini analiz edeceğiz ve bir daha yaşamamak için önleyici tedbirleri konuşacağız.
Mail Kuyruğu Nedir ve Ne Zaman “Yüksek” Sayılır?
Postfix, Exim veya Sendmail gibi MTA’lar (Mail Transfer Agent) gelen mesajları doğrudan iletmek yerine önce bir kuyruğa alır. Bu kuyruk, mesajların geçici olarak depolandığı, yeniden deneme mekanizmalarının işlediği bir sistemdir. Normal şartlarda bu kuyruk kısa sürede boşalır.
Peki ne zaman alarm verilmeli?
- Kuyrukta 500’den fazla mesaj varsa ve artmaya devam ediyorsa
- Kuyruk boyutu son 30 dakikada %50’den fazla büyüdüyse
- Mesajların delivery zamanları saatleri aşmaya başladıysa
- Bounce (geri dönen) mesaj sayısı normalin üçte birine yaklaştıysa
Önce mevcut durumu anlamak için temel komutları çalıştıralım:
# Toplam kuyruk boyutunu görmek için
postqueue -p | tail -n 1
# Daha detaylı kuyruk analizi
postqueue -p | grep -c "^[A-F0-9]"
# Kuyrukta bekleyen mesajları listele (ilk 50)
postqueue -p | head -100
# Kuyruğu mail başlıklarıyla birlikte gör
postqueue -p | awk '/^[A-F0-9]/{print $1}' | head -20 | xargs -I{} postcat -q {}
Sebep Analizi: Nereden Başlamalı?
Yüksek kuyruk sorunlarının birçok farklı kaynağı olabilir. Deneyimlerime göre bu sorunları beş ana kategoriye ayırabiliriz.
1. Spam ve Kötü Amaçlı Yazılım Kaynaklı Sorunlar
En sık karşılaştığım senaryo şu: Bir web uygulaması (WordPress, Joomla, özel PHP uygulaması) ele geçirilmiş ve spam göndermeye başlamış. Kuyruk bir anda on binlerce mesajla dolmuş.
# Gönderici IP ve domain analizi
postqueue -p | awk '/^[A-F0-9]/{id=$1} /^[[:space:]]/{print id, $0}' |
grep "From:" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
# Hangi PHP scriptinin mail gönderdiğini bul
# Mail log'unda uid kontrolü
grep "postfix/pickup" /var/log/mail.log | grep "uid=" |
awk '{print $NF}' | sort | uniq -c | sort -rn
# Apache/Nginx process tree ile mail gönderen scripti bul
lsof -i :25 | grep ESTABLISHED
Burada dikkat edilmesi gereken nokta: Eğer uid=33 (www-data) görüyorsanız, bir web uygulaması aracılığıyla spam gönderiliyordur.
# Kuyruktaki mesajların envelope sender analizi
postqueue -p | grep "^[A-F0-9]" | awk '{print $7}' |
sort | uniq -c | sort -rn | head -30
# Belirli bir domain'den gelen tüm kuyruk itemlarını sil
postsuper -d ALL deferred
# DIKKAT: Bu komutu çalıştırmadan önce analiz yapın!
# Sadece belirli bir göndericiden gelenleri sil
postqueue -p | grep "[email protected]" |
awk '{print $1}' | tr -d '*!' | postsuper -d -
2. Hedef Sunucu Problemleri
Bazen sorun bizim tarafımızda değil, hedef mail sunucusundadır. Karşı taraf geçici hatalar döndürüyor ve mesajlar “deferred” durumunda birikiyordur.
# Deferred mesajların neden bekletildiğini gör
postqueue -p | grep "^s" | grep -v "^$" |
sort | uniq -c | sort -rn | head -20
# Belirli bir domain'e gönderim denemelerini takip et
mailq | grep "gmail.com|yahoo.com|hotmail.com" | head -30
# Mail log'unda connection hatalarını filtrele
grep "Connection refused|Connection timed out|Host or domain name not found"
/var/log/mail.log | awk '{print $7}' | sort | uniq -c | sort -rn
# MX kayıt kontrolü
dig MX problematic-domain.com +short
nslookup -type=mx problematic-domain.com
Gerçek dünya senaryosu: Bir müşteride toplu newsletter gönderimi sırasında Gmail’in rate limiting uygulaması sonucu 15.000 mesaj deferred kuyruğuna düşmüştü. Çözüm olarak gönderim hızını sınırlandırmak gerekti.
# main.cf'te rate limiting ayarları
# /etc/postfix/main.cf
smtp_destination_concurrency_limit = 2
smtp_destination_rate_delay = 1s
smtp_extra_recipient_limit = 10
# Konfigürasyonu yeniden yükle
postfix reload
3. DNS ve Reverse DNS Sorunları
PTR kaydı olmayan veya yanlış yapılandırılmış sunucular, büyük mail sağlayıcıları tarafından reddedilir ve bu durum kuyruğun dolmasına yol açar.
# Sunucunun PTR kaydını kontrol et
dig -x $(curl -s ifconfig.me) +short
# Forward confirmed reverse DNS testi
host $(dig -x $(curl -s ifconfig.me) +short | head -1)
# SPF, DKIM, DMARC kayıt kontrolü
dig TXT yourdomain.com | grep "v=spf"
dig TXT default._domainkey.yourdomain.com | grep "v=DKIM"
dig TXT _dmarc.yourdomain.com | grep "v=DMARC"
# Mail log'unda reject sebeplerini analiz et
grep "reject:" /var/log/mail.log |
awk '{$1=$2=$3=$4=$5=""; print $0}' |
sort | uniq -c | sort -rn | head -20
4. Yerel Kaynak Tükenmesi
Disk dolması, inode tükenmesi, memory baskısı gibi sistem kaynak sorunları da kuyruk birikimine yol açar.
# Disk kullanımını kontrol et
df -h /var/spool/postfix/
# Inode kullanımını kontrol et (çok önemli!)
df -i /var/spool/postfix/
# Postfix spool dizinindeki dosya sayısını kontrol et
find /var/spool/postfix/ -type f | wc -l
# Mail spool detaylı analiz
du -sh /var/spool/postfix/*/
ls -la /var/spool/postfix/deferred/ | wc -l
# Sistem memory ve load durumu
free -m
uptime
vmstat 1 5
Deneyimlerimden: Bir sunucuda inode %100 dolmuştu ama disk kullanımı %40’tı. Binlerce küçük kuyruk dosyası inode’ları tüketmişti. Bu durumda yeni dosya oluşturulamıyor ve postfix sessizce hata veriyordu.
5. Postfix Konfigürasyon Sorunları
Yanlış konfigürasyon, mail loop’larına veya aşırı yeniden deneme davranışlarına yol açabilir.
# Postfix konfigürasyonu doğrula
postfix check
# Aktif konfigürasyon parametrelerini listele
postconf -n
# Mail loop kontrolü - kendi kendine gönderim
postconf -n | grep "mydestination|myhostname|myorigin"
# Queue runner sayısını kontrol et
postconf -n | grep "maximal_queue_lifetime|bounce_queue_lifetime|minimal_backoff_time|maximal_backoff_time"
# /etc/postfix/main.cf için önerilen queue parametreleri
# Bu değerleri durumunuza göre ayarlayın
# Maksimum kuyrukta bekleme süresi (varsayılan 5 gün, çok uzun!)
maximal_queue_lifetime = 1d
bounce_queue_lifetime = 1h
# Yeniden deneme süreleri
minimal_backoff_time = 300s
maximal_backoff_time = 4000s
# Eş zamanlı bağlantı sayısı
smtp_destination_concurrency_limit = 5
default_process_limit = 100
Acil Müdahale: Kuyruk Temizleme Stratejileri
Durum kritikse, önce yangını söndürmek gerekiyor. Ama dikkatli olmak şart, meşru mesajları silmemek için.
# Sadece deferred mesajları sil (dikkatli kullan!)
postsuper -d ALL deferred
# Tüm kuyruğu temizle (son çare!)
postsuper -d ALL
# Belirli bir message ID'yi sil
postsuper -d MESSAGEID
# Kuyruğu durdur (müdahale için zaman kazanmak)
postsuper -h ALL
# Durdurulan kuyruğu yeniden başlat
postsuper -H ALL
# Deferred mesajları hemen yeniden dene
postqueue -f
# Belirli bir domain için yeniden deneme
postqueue -s domain.com
Bir acil müdahale scripti yazalım:
#!/bin/bash
# emergency_queue_analysis.sh
# Yüksek kuyruk durumu için hızlı analiz scripti
QUEUE_SIZE=$(postqueue -p | tail -1 | awk '{print $5}')
LOG_FILE="/var/log/queue_emergency_$(date +%Y%m%d_%H%M%S).log"
echo "=== KUYRUK ACİL ANALİZİ ===" | tee $LOG_FILE
echo "Tarih: $(date)" | tee -a $LOG_FILE
echo "Toplam kuyruk: $QUEUE_SIZE mesaj" | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
echo "--- TOP 10 GÖNDERICI ---" | tee -a $LOG_FILE
postqueue -p | grep "^[A-F0-9]" | awk '{print $7}' |
sort | uniq -c | sort -rn | head -10 | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
echo "--- TOP 10 ALICI DOMAIN ---" | tee -a $LOG_FILE
postqueue -p | grep -oP 'to=<[^>]+>' |
awk -F@ '{print $2}' | tr -d '>' |
sort | uniq -c | sort -rn | head -10 | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
echo "--- HATA MESAJLARI ---" | tee -a $LOG_FILE
postqueue -p | grep "^s" | grep -v "^$" |
sort | uniq -c | sort -rn | head -15 | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
echo "--- DİSK DURUMU ---" | tee -a $LOG_FILE
df -h /var/spool/postfix/ | tee -a $LOG_FILE
df -i /var/spool/postfix/ | tee -a $LOG_FILE
echo "Rapor kaydedildi: $LOG_FILE"
Önleyici Tedbirler: Bir Daha Yaşamamak İçin
Yangını söndürdükten sonra asıl iş başlıyor. Aynı sorunu tekrar yaşamamak için alınması gereken önlemler:
Monitoring ve Alerting Kurulumu
#!/bin/bash
# queue_monitor.sh - Cron'a ekle: */5 * * * * /usr/local/bin/queue_monitor.sh
THRESHOLD=500
ALERT_EMAIL="[email protected]"
QUEUE_SIZE=$(postqueue -p | grep -c "^[A-F0-9]" 2>/dev/null || echo 0)
HOSTNAME=$(hostname -f)
if [ "$QUEUE_SIZE" -gt "$THRESHOLD" ]; then
SUBJECT="[UYARI] $HOSTNAME Mail Kuyruğu Yüksek: $QUEUE_SIZE mesaj"
BODY="Mail sunucusu kuyruğu $THRESHOLD sınırını aştı.
Mevcut kuyruk boyutu: $QUEUE_SIZE
Zaman: $(date)
Sunucu: $HOSTNAME
Top 10 gönderici:
$(postqueue -p | grep '^[A-F0-9]' | awk '{print $7}' | sort | uniq -c | sort -rn | head -10)
Top 10 hata:
$(postqueue -p | grep '^s' | grep -v '^$' | sort | uniq -c | sort -rn | head -10)
Lütfen kontrol edin!"
echo "$BODY" | mail -s "$SUBJECT" "$ALERT_EMAIL"
# Ayrıca log'a yaz
echo "$(date) - UYARI: Kuyruk boyutu $QUEUE_SIZE" >> /var/log/queue_monitor.log
fi
Rate Limiting ve Gönderim Kısıtlamaları
Özellikle web uygulamalarından gelen ani mail trafiğini sınırlamak için:
# /etc/postfix/main.cf
# Web uygulamalarından gelen gönderim hızını sınırla
smtpd_client_message_rate_limit = 100
smtpd_client_recipient_rate_limit = 200
anvil_rate_time_unit = 60s
# Authenticated user başına rate limit
smtpd_client_auth_rate_limit = 50
# Submission portunda daha sıkı limitler
# /etc/postfix/master.cf submission satırını düzenle
# submission inet n - n - - smtpd
# -o smtpd_client_message_rate_limit=20
# Konfigürasyonu test et ve yükle
postfix check && postfix reload
Fail2ban ile Spam Botlarını Engelle
# /etc/fail2ban/jail.local
[postfix-sasl]
enabled = true
port = smtp,465,submission
filter = postfix-sasl
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
findtime = 300
[postfix]
enabled = true
port = smtp,465,submission
filter = postfix
logpath = /var/log/mail.log
maxretry = 5
bantime = 7200
findtime = 600
PHP Mail Kötüye Kullanımını Önleme
Web sunucularda mail abuse’u önlemek için:
# PHP'nin mail() fonksiyonunu logla
# /etc/php/8.1/apache2/php.ini veya php-fpm.ini
# sendmail_path = /usr/local/bin/phpmailer_wrapper.sh -t -i
# Wrapper script
cat > /usr/local/bin/phpmailer_wrapper.sh << 'EOF'
#!/bin/bash
# Hangi scriptin mail gönderdiğini logla
SCRIPT=$(cat /proc/$PPID/cmdline | tr '' ' ' 2>/dev/null)
echo "$(date): UID=$(id -u) PPID=$PPID SCRIPT=$SCRIPT" >> /var/log/php_mail.log
exec /usr/sbin/sendmail "$@"
EOF
chmod +x /usr/local/bin/phpmailer_wrapper.sh
Düzenli Kuyruk Bakımı
#!/bin/bash
# /etc/cron.daily/postfix_maintenance.sh
# Her gece çalışacak bakım scripti
# 3 günden eski deferred mesajları temizle
find /var/spool/postfix/deferred -type f -mtime +3 -exec basename {} ; |
while read id; do
postsuper -d "$id" 2>/dev/null
done
# Bounce mesajlarını analiz et ve logla
BOUNCE_COUNT=$(ls /var/spool/postfix/bounce/ 2>/dev/null | wc -l)
echo "$(date) - Bounce mesaj sayısı: $BOUNCE_COUNT" >> /var/log/postfix_maintenance.log
# Disk ve inode kullanımını logla
echo "$(date) - Disk: $(df -h /var/spool/postfix/ | tail -1)" >> /var/log/postfix_maintenance.log
echo "$(date) - Inode: $(df -i /var/spool/postfix/ | tail -1)" >> /var/log/postfix_maintenance.log
Log Analizi ile Kök Neden Tespiti
Mail sorunlarında log analizi hayat kurtarır. Doğru log okumayı bilmek kritik.
# Saatlik mail trafiğini görselleştir
grep "$(date +%b %d)" /var/log/mail.log |
awk '{print $3}' | cut -d: -f1 |
sort | uniq -c |
awk '{printf "%s:00 - %d mesajn", $2, $1}'
# En çok reject edilen IP'leri bul
grep "NOQUEUE: reject" /var/log/mail.log |
grep -oP 'd+.d+.d+.d+' |
sort | uniq -c | sort -rn | head -20
# Belirli bir saatte ne olduğunu analiz et
grep "Jun 15 09:" /var/log/mail.log |
grep -E "reject|deferred|bounced|sent" |
awk '{print $6}' | sort | uniq -c | sort -rn
# Authentication hatalarını izle
grep "authentication failed|SASL LOGIN authentication failed"
/var/log/mail.log |
awk '{print $9}' | sort | uniq -c | sort -rn | head -10
Graylist ve DNSBL Entegrasyonu
Kuyruk sorunlarını önlemenin en etkili yollarından biri spam’i daha girmeden engellemek.
# Postfix'te DNSBL kontrolü - /etc/postfix/main.cf
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client bl.spamcop.net,
reject_rbl_client dnsbl.sorbs.net,
permit
# Greylisting için postgrey entegrasyonu
# Ubuntu/Debian:
apt-get install postgrey
# /etc/postfix/main.cf'e ekle
smtpd_recipient_restrictions =
...
check_policy_service inet:127.0.0.1:10023,
permit
Postfix Performans Tuning
Kuyruk işleme hızını artırmak için temel tuning parametreleri:
- default_process_limit: Eş zamanlı çalışan process sayısı, varsayılan 100, yüklü sunucularda 200’e çıkarılabilir
- smtp_connect_timeout: SMTP bağlantı timeout süresi, 30s ideal
- smtp_helo_timeout: HELO komutu timeout, 300s yeterli
- queue_run_delay: Kuyruk tarama aralığı, 300s varsayılan, 60s’e düşürülebilir
- transport_retry_time: Başarısız transport sonrası bekleme, 60s önerilir
- local_destination_concurrency_limit: Lokal teslimatta eş zamanlılık, 4-8 arası ideal
- smtp_destination_concurrency_limit: Her domain için max bağlantı, 5-10 arası
Sonuç
Yüksek mail kuyruğu problemi, reactive değil proactive bir yaklaşımla yönetilmesi gereken bir konudur. Sorunu yaşandıktan sonra çözmek elbette gerekli ama asıl hedef sorunun oluşmasını engellemek olmalı.
Özetlersek kritik adımlar şunlar: İlk olarak monitoring kurulumu yapın, kuyruk boyutu belirli bir eşiği geçtiğinde anında haberdar olun. İkincisi, web uygulamalarını izole edin ve PHP mail kötüye kullanımına karşı wrapper scriptleri kullanın. Üçüncüsü, rate limiting uygulayın, hem gönderim hem de alım tarafında. Dördüncüsü, DNS kayıtlarınızı düzenli kontrol edin, SPF, DKIM ve DMARC kayıtlarının eksiksiz ve doğru olduğundan emin olun. Son olarak, düzenli log analizi yapın, anormal pattern’leri erken tespit edin.
Mail sunucusu yönetimi deneyim gerektiren bir alan. Her incident bir öğrenme fırsatıdır. Bu yazıdaki komutları ve scriptleri kendi ortamınıza uyarlayarak runbook’unuzu oluşturun. Bir dahaki sefere sabah 07:00’de telefon çaldığında, paniklemek yerine runbook’unuzu açıp sistematik ilerleyeceksiniz.
Sorularınız veya farklı senaryolarınız varsa yorumlarda paylaşın, birlikte çözelim.
