Mail Gecikmesi: Kuyruk ve Routing Sorunlarını Giderme
Sabah işe geldiniz, müşterilerden şikayetler yağıyor: “Mail gelmiyor”, “Gönderdiğim mail karşı tarafa ulaşmadı”, “3 saattir bekliyorum”. Ekrana bakıyorsunuz, sunucu ayakta, servis çalışıyor ama bir şeyler yanlış. Mail gecikmesi ve kuyruk sorunları, sysadmin hayatının en sinir bozucu problemlerinden biridir çünkü hem teknik hem de iş etkisi çok hızlı büyür. Bu yazıda Postfix üzerinden giderek mail gecikmelerinin kök nedenlerini nasıl bulacağınızı ve çözeceğinizi adım adım anlatacağım.
Durumu Hızla Anlamak: İlk Kontroller
Paniklemeden önce mevcut durumu bir görüntüleyin. Kaç mail kuyrukta bekliyor, ne zamandan beri bekliyor, hangi sunuculara gönderilmeye çalışılıyor? Bu sorulara cevap vermeden ellerinizi klavyeye götürmeyin.
# Postfix kuyruk özetini gör
postqueue -p | head -50
# Toplam kuyruk sayısını öğren
postqueue -p | grep -c "^[A-F0-9]"
# Kuyruk boyutunu MB olarak gör
du -sh /var/spool/postfix/deferred/
du -sh /var/spool/postfix/active/
du -sh /var/spool/postfix/bounce/
Burada dikkat etmeniz gereken iki kritik dizin var: deferred ve active. active dizini şu an işlenmekte olan mailleri tutar, deferred ise ertelenmiş yani bir sebepten gönderilememiş olan mailleri. Eğer deferred dizini şişmişse ve active neredeyse boşsa, sistem mailleri işlemeye çalışıyor ama bir yerden duvar yiyor demektir.
# Hangi hedef domainlere mail gönderilemiyor?
postqueue -p | grep "^[A-F0-9]" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
# Mail loglarını canlı takip et
tail -f /var/log/mail.log | grep -E "(deferred|bounced|reject|error)"
# Son 1 saatteki log özetini çek
grep "$(date +'%b %d %H')" /var/log/mail.log | grep -E "(status=deferred|status=bounced)" | wc -l
Mail Kuyruğunu Detaylı İncelemek
Genel tabloyu gördünüz, şimdi biraz daha derine inelim. Postfix’in kuyruğundaki her mail bir ID’ye sahip ve o ID ile detaylı bilgi alabilirsiniz.
# Belirli bir mail ID'sinin detayını gör
postcat -q MAILID
# Örnek:
postcat -q 3A2B4C1234
# Kuyruktaki tüm maillerin neden ertelendiğini toplu gör
postqueue -p | grep -A2 "^[A-F0-9]" | grep "connect|refused|timeout|lookup"
# Belirli bir domain'e takılı kalan mailleri filtrele
postqueue -p | grep "@gmail.com"
Gerçek dünyadan bir senaryo: Bir müşterimizde deferred kuyruğunda 12.000’in üzerinde mail birikmişti. postqueue -p çıktısına bakınca hepsinin Host or domain name not found hatasıyla takıldığını gördük. Sorun çok basitti: DNS sunucusu değişmişti ama /etc/resolv.conf güncellenmemişti. Mail sunucusu MX kayıtlarını çözümleyemiyordu ve tüm mailler deferred’a düşüyordu.
DNS Sorunları: En Sık Karşılaşılan Kök Neden
Mail gecikmelerinin büyük çoğunluğunun arkasında DNS sorunları yatar. Hem gönderici hem de alıcı tarafta DNS çözümleme problemi olabilir.
# Postfix'in kullandığı DNS'i kontrol et
cat /etc/resolv.conf
# Hedef domain'in MX kaydını sorgula
dig MX gmail.com
dig MX @8.8.8.8 gmail.com
# Reverse DNS (PTR) kaydını kontrol et - spam filtreleri için kritik
dig -x $(hostname -I | awk '{print $1}')
# Postfix'in kendi domain'ini nasıl çözdüğünü test et
postfix check
# nslookup ile hızlı MX sorgusu
nslookup -type=MX example.com
Özellikle PTR kaydı olmayan sunuculardan gelen mailler büyük provider’lar tarafından ya reddedilir ya da spam klasörüne düşürülür. Eğer IP adresinizin reverse DNS’i yoksa, hosting firmanıza ya da ISP’nize başvurmanız gerekir.
DNS sorununu çözdükten sonra deferred kuyruğunu yeniden denemeye zorlayabilirsiniz:
# Tüm deferred mailleri hemen yeniden göndermeyi dene
postqueue -f
# Veya flush komutuyla
postfix flush
# Belirli bir domain için yeniden deneme
postqueue -s gmail.com
SMTP Bağlantı ve Port Sorunları
DNS doğruysa bir sonraki şüpheli bağlantı katmanıdır. Hedef sunucuya 25. port üzerinden ulaşabiliyor musunuz?
# Hedef MX sunucusuna port 25 testi
telnet mx1.example.com 25
# Eğer telnet yoksa netcat ile
nc -zv mx1.example.com 25
# Postfix'in gönderdiği SMTP konuşmasını izle
tcpdump -i any -nn port 25 -A 2>/dev/null | head -100
# Hangi porttan bağlantı çıkıyor, hangi IP kullanılıyor
ss -tnp | grep :25
netstat -tnp | grep :25
Birçok cloud provider (AWS, GCP, Azure, Hetzner) varsayılan olarak port 25’i outbound yönde bloke eder. Bu çok yaygın bir sorundur ve yeni kurulmuş sunucularda sıkça karşılaşılır. Eğer telnet mx1.gmail.com 25 komutu hiç bağlanamıyorsa muhtemelen provider tarafında engel vardır.
Bu durumda iki seçeneğiniz var:
- Provider’dan port 25’i açmalarını talep etmek
- Bir SMTP relay kullanmak (SendGrid, Mailgun, Amazon SES gibi)
Relay kullanıyorsanız Postfix konfigürasyonu şöyle olur:
# /etc/postfix/main.cf içine relay ayarları
relayhost = [smtp.sendgrid.net]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
# Kimlik bilgilerini kaydet
echo "[smtp.sendgrid.net]:587 apikey:YOUR_API_KEY" > /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd
# Postfix'i yeniden yükle
systemctl reload postfix
TLS Sorunları ve Sertifika Hataları
Modern mail sunucuları TLS şifrelemesi kullanır ve hatalı sertifika konfigürasyonu mail gecikmelerine yol açabilir.
# Mail loglarında TLS hatalarını ara
grep -E "TLS|SSL|certificate" /var/log/mail.log | tail -30
# Postfix TLS konfigürasyonunu kontrol et
postconf -n | grep tls
# Sertifikanın geçerliliğini test et
openssl s_client -connect mail.example.com:25 -starttls smtp 2>/dev/null | openssl x509 -noout -dates
# Sertifika zincirini kontrol et
openssl s_client -connect mail.example.com:25 -starttls smtp -showcerts 2>/dev/null
Logda certificate verify failed veya untrusted certificate gibi mesajlar görüyorsanız, gönderici tarafında TLS doğrulama seviyesini geçici olarak düşürebilirsiniz (production’da dikkatli kullanın):
# main.cf içinde
smtp_tls_security_level = may
# "encrypt" veya "verify" yerine "may" kullanmak zorunlu TLS'i kaldırır
# Bu sadece geçici bir çözüm, asıl sorunu (sertifika) düzeltin!
postfix reload
Kuyruk İşleme Performansı: Concurrency ve Worker Ayarları
Binlerce mailiniz kuyrukta bekliyor ve flush diyorsunuz ama çok yavaş gönderiliyor. Bu durumda Postfix’in worker konfigürasyonuna bakmanız gerekir.
# Mevcut master.cf ve concurrency ayarlarını gör
cat /etc/postfix/master.cf | grep smtp
# Postfix'in şu an kaç worker çalıştırdığını gör
ps aux | grep -c "[p]ickup|[q]mgr|[s]mtp"
# Hangi kaynaklar kullanılıyor
postconf default_process_limit
postconf smtp_destination_concurrency_limit
postconf smtp_destination_rate_delay
Büyük toplu gönderimleriniz varsa ve hedef domain başına bağlantı limiti düşükse, bu bir darboğaz oluşturabilir. Örneğin varsayılan olarak tek bir hedefe 20 eşzamanlı bağlantı açılabilir, bunu artırabilirsiniz:
# /etc/postfix/main.cf
default_process_limit = 100
smtp_destination_concurrency_limit = 40
smtp_destination_rate_delay = 0s
smtp_extra_recipient_limit = 1000
# Kuyruk işleyici ayarları
qmgr_message_active_limit = 20000
qmgr_message_recipient_limit = 20000
postfix reload
Ancak burada dikkatli olun: çok agresif gönderim yaparsanız hedef sunucular sizi rate-limit’e alır veya tamamen bloke eder. Gmail gibi büyük provider’ların connection limitleri var ve bu limitleri aşarsanız 421 Too many connections hatası alırsınız.
Routing Sorunları: Transport Map ve Relay Konfigürasyonu
Mail’in nereye gideceğini belirleyen routing kuralları yanlış yapılandırılmışsa, mailler ya yanlış yere gider ya da hiç gidemez.
# Postfix'in bir adres için nasıl route planladığını test et
postmap -q [email protected] hash:/etc/postfix/transport
# Tüm transport haritasını gör
cat /etc/postfix/transport
# Postfix'in routing kararını simüle et
postconf -n | grep "transport|relay|route"
# Virtual domain routing
postconf -n | grep "virtual|mydestination|relay_domains"
Gerçek dünya senaryosu: Bir kurumsal müşteride kendi mail sunucusu hem şirket içi hem de dış domain’lere mail gönderiyordu. İç domain mailler Exchange’e, dış domainler direkt internete gidecekti. Ama transport tablosunda bir typo yüzünden bazı dış domainler de Exchange’e route ediliyordu ve Exchange bu mailleri kabul etmeyip geri atıyordu. Sorun sadece postmap -q domain.com hash:/etc/postfix/transport ile birkaç dakikada bulundu.
# Transport tablosunu düzenle
cat /etc/postfix/transport
# example.com smtp:[mail.example.com]:25
# .example.com smtp:[mail.example.com]:25
# * smtp: (veya boş bırak)
# Değişiklikten sonra mutlaka derle
postmap /etc/postfix/transport
postfix reload
Spam Filtresi ve Kara Liste Kontrolü
Mail sunucunuz sorunsuz çalışıyor ama karşı taraf maillerinizi kabul etmiyor. Bu durumda IP itibarınızı kontrol etmelisiniz.
# Mail loglarında reject sebeplerini gör
grep "reject|blocked|blacklist|RBL" /var/log/mail.log | tail -50
# SPF kaydını kontrol et
dig TXT example.com | grep "v=spf"
# DKIM konfigürasyonunu test et
dig TXT default._domainkey.example.com
# DMARC kaydını gör
dig TXT _dmarc.example.com
IP’nizin kara listede olup olmadığını komut satırından da kontrol edebilirsiniz:
# IP'yi çeşitli RBL'lerde sorgula (IP'yi tersine çevir)
# Örnek IP: 1.2.3.4 -> 4.3.2.1.zen.spamhaus.org
IP="YOUR.IP.HERE"
REVERSED=$(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}')
for RBL in zen.spamhaus.org bl.spamcop.net dnsbl.sorbs.net b.barracudacentral.org; do
RESULT=$(dig +short ${REVERSED}.${RBL})
if [ -n "$RESULT" ]; then
echo "LISTED in $RBL: $RESULT"
else
echo "Clean in $RBL"
fi
done
Eğer kara listedeyseniz ilgili RBL’nin web sitesinden delisting talebinde bulunmanız gerekir. Spamhaus için bu genellikle 24-48 saat sürer. Bu süre zarfında başka bir IP üzerinden veya relay üzerinden gönderim yapabilirsiniz.
Disk ve Sistem Kaynakları
Bazen sorun çok daha basittir: disk dolmuştur ya da sistem kaynakları tükenmektedir.
# Disk kullanımını kontrol et
df -h /var/spool/postfix/
# Inode tükenmesini kontrol et (bu çok önemli!)
df -i /var/spool/postfix/
# Postfix spool dizinindeki dosya sayısı
find /var/spool/postfix/ -type f | wc -l
# Sistem memory durumu
free -h
# Postfix process'lerinin durumu
systemctl status postfix
journalctl -u postfix --since "1 hour ago" | tail -50
Inode tükenmesi çok sinsice bir sorun olabilir: disk alanı var gibi görünür ama dosya oluşturulamaz. Çok sayıda küçük mail dosyası inode’ları bitirebilir. Bu durumda deferred kuyruğunu temizlemeniz gerekebilir.
# Deferred kuyruğunu tamamen temizle (dikkatli! mailler silinir)
postsuper -d ALL deferred
# Sadece belirli bir domain'e ait takılı kalan mailleri sil
postqueue -p | grep "@problem-domain.com" | awk '{print $1}' | tr -d '*!' | postsuper -d -
# Belirli bir yaşın üzerindeki mailleri sil (örnek: 7 günden eski)
find /var/spool/postfix/deferred -mtime +7 -delete
postsuper -r ALL deferred # Kuyruğu yeniden tara
Log Analizi ile Sorun Tespiti
İyi bir sysadmin log okumayı sever. Mail logları çok konuşkan olabilir ama pattern’leri bilirseniz iğneyi samanlıkta bulursunuz.
# Belirli bir mail ID'sini takip et (başından sonuna)
grep "MAILID" /var/log/mail.log
# En çok hata veren IP'leri bul
grep "reject" /var/log/mail.log | awk '{print $8}' | cut -d= -f2 | sort | uniq -c | sort -rn | head -10
# Saatlik mail istatistiklerini gör
grep "status=sent" /var/log/mail.log | awk '{print $3}' | cut -d: -f1 | sort | uniq -c
# Bounce nedenlerini grupla
grep "status=bounced" /var/log/mail.log | grep -oP "said: d{3}.*" | sort | uniq -c | sort -rn | head -20
# Gece yarısı kuyruk analizini script'e dökelim
cat > /usr/local/bin/mail-queue-check.sh << 'EOF'
#!/bin/bash
QUEUE_SIZE=$(postqueue -p | grep -c "^[A-F0-9]" 2>/dev/null || echo 0)
DEFERRED_SIZE=$(du -sh /var/spool/postfix/deferred/ 2>/dev/null | cut -f1)
echo "$(date): Queue: $QUEUE_SIZE messages, Deferred dir: $DEFERRED_SIZE"
if [ "$QUEUE_SIZE" -gt 1000 ]; then
echo "UYARI: Kuyrukta $QUEUE_SIZE mail var!" | mail -s "Mail Kuyruk Alarmı" [email protected]
fi
EOF
chmod +x /usr/local/bin/mail-queue-check.sh
# Cron'a ekle
echo "*/15 * * * * /usr/local/bin/mail-queue-check.sh >> /var/log/mail-queue.log" | crontab -
Postfix Konfigürasyon Doğrulama
Tüm bu kontrollerin yanı sıra Postfix konfigürasyonunun kendisini de doğrulamanız gerekir.
# Konfigürasyon sözdizimini kontrol et
postfix check
# Tüm non-default ayarları listele
postconf -n
# Belirli bir parametrenin değerini sorgula
postconf mydomain
postconf myhostname
postconf mynetworks
# Postfix'i reload et (servisi durdurmadan)
postfix reload
# Tam restart gerekirse
systemctl restart postfix
# Postfix versiyonunu öğren
postconf -d mail_version
Gerçek Dünya Sorun Giderme Senaryosu
Bir müşterimizde yaşanan gerçek bir vakayı aktarayım. Sabah 9’da müşteri aradı: “Dün gece 23’ten beri mail gitmiyor.” Adımlar şöyle gelişti:
Önce postqueue -p | wc -l ile 4.200 mailin kuyrukta olduğunu gördük. postqueue -p | tail -20 ile hata mesajına baktık: Connection timed out. Sonra telnet mx1.hedefdomain.com 25 denedik, bağlantı olmadı. Ama ping mx1.hedefdomain.com başardı, sadece port 25 cevap vermiyordu. traceroute -p 25 mx1.hedefdomain.com ile baktık; trafik firewall’da takılıyordu. Güvenlik ekibi gece bir değişiklik yapmış ve outbound port 25’i bloke etmişti. Firewall kuralı düzeltildikten sonra postqueue -f ile kuyruğu tetikledik ve 20 dakikada tüm mailler ulaştı.
Bu vaka şunu gösteriyor: mail sunucusu tamamen sağlıklı olabilir, sorun altyapının başka bir katmanında olabilir. Her zaman network katmanını da kontrol edin.
Monitoring ve Proaktif Önlemler
Sorun çıkmadan önce önlem almak her zaman daha iyidir.
# Pflogsumm ile günlük mail raporu oluştur
apt-get install pflogsumm # veya yum install postfix-perl-scripts
# Günlük rapor
pflogsumm /var/log/mail.log
# Cron ile her gün sabah raporu al
echo "0 7 * * * pflogsumm /var/log/mail.log | mail -s 'Daily Mail Report' [email protected]" | crontab -
# Mailq boyutunu Nagios/Zabbix için kontrol et
# Eğer kuyruk 500'ü geçerse uyar
QUEUE=$(mailq | grep -c "^[A-F0-9]")
if [ $QUEUE -gt 500 ]; then
exit 2 # Critical
elif [ $QUEUE -gt 100 ]; then
exit 1 # Warning
fi
exit 0 # OK
Düzenli yapılması gereken kontroller listesi:
- Her gün: Mail kuyruğu boyutunu kontrol et
- Her hafta: Bounce oranlarını analiz et
- Her ay: IP itibar kontrolü yap (MXToolbox, Spamhaus)
- Her ay: SPF, DKIM, DMARC kayıtlarını doğrula
- Her 3 ayda: TLS sertifika son kullanma tarihlerini kontrol et
- Her 6 ayda: Postfix konfigürasyonunu security açısından review et
Sonuç
Mail gecikmesi sorunları sinir bozucu ama büyük çoğunluğu sistematik bir yaklaşımla çözülebilir. Paniklemeden önce kuyruğa bakın, log okuyun, DNS’i kontrol edin, network bağlantısını test edin. Sorunların %80’i bu dört adımda bulunur.
Önemli bir not: production ortamında konfigürasyon değişikliği yapmadan önce mutlaka yedek alın ve değişikliği test ortamında deneyin. postconf -n > /root/postfix-backup-$(date +%Y%m%d).conf komutu ile mevcut konfigürasyonu kaydedebilirsiniz.
Son olarak, mail altyapısı tekil bir bileşen değildir. DNS, network, firewall, uygulama katmanı ve karşı tarafın politikaları bir arada çalışır. Sorun giderirken bu bütüncül bakış açısını kaybetmeyin ve her değişikliği log üzerinden doğrulayın. İyi loglar iyi uyku demektir.
