Exchange Server’da Kuyruk Yönetimi ve Mail Akış Sorunları

Bir Exchange ortamında mail kuyruklarının kontrolden çıktığı anı muhtemelen hepiniz yaşamışsınızdır. Sabah 08:00’de ofise geliyorsunuz, helpdesk telefonu çalmaya başlıyor, “mailler gitmiyor” şikayetleri birikiyor ve siz henüz kahvenizi bile içmemişsiniz. İşte bu yazıda tam olarak o anlar için ne yapmanız gerektiğini, Exchange kuyruk yönetimini derinlemesine ve gerçek senaryolar üzerinden anlatacağım.

Exchange Kuyruk Mimarisini Anlamak

Exchange Server’da mail akışı, birden fazla kuyruk bileşeni üzerinden yürür. Bunu anlamadan sorun gidermek, karanlıkta el yordamıyla iş yapmaya benzer.

Transport servisinin kuyruk yapısı şöyle işler:

  • Submission Queue (Gönderim Kuyruğu): Mesajların ilk teslim alındığı ve kategorize işlemini beklediği yer
  • Mailbox Delivery Queue: Hedef mailbox veritabanına teslim bekleyen mesajlar
  • Remote Delivery Queue: Harici domainlere ya da başka Exchange sunuculara gidecek mesajlar
  • Poison Message Queue: İşlenemeyen ve transport servisi çökertme riski taşıyan mesajlar
  • Unreachable Queue: Rotası belirlenemeyen mesajlar için geçici bekleme alanı
  • Shadow Queue: Yedeklilik için tutulan mesaj kopyaları (Shadow Redundancy aktifse)

Kuyrukların bu şekilde ayrışması çok önemli, çünkü hangi kuyrukta tıkanma yaşandığını bilmek, sorunun kaynağına doğrudan işaret eder.

Queue Viewer ve PowerShell ile Durum Tespiti

Grafik arayüz sevenler için Exchange Toolbox içindeki Queue Viewer kullanışlıdır ama gerçek anlamda kuyruk yönetimi PowerShell olmadan olmaz. Ben her zaman PowerShell’i tercih ederim, çünkü otomasyon yapabiliyorsunuz ve çıktıları filtreleyebiliyorsunuz.

Exchange Management Shell’de temel kuyruk sorgusu:

Get-Queue | Sort-Object MessageCount -Descending | Format-Table Identity, Status, MessageCount, NextHopDomain -AutoSize

Bu komut size anlık kuyruk durumunu önem sırasına göre gösterir. MessageCount sütununda binlerle ifade edilen değerler görüyorsanız ciddi bir sorun var demektir.

Belirli bir kuyruğun detaylarına inmek için:

Get-Queue -Identity "SUNUCUADIRemote Delivery12" | Format-List *

Buradaki çıktıda LastError alanına özellikle dikkat edin. Bu alan size genellikle sorunun tam sebebini söyler: DNS çözümleme hatası mı, bağlantı reddi mi, TLS el sıkışma sorunu mu hepsi burada yazar.

Tüm kuyruklardaki mesajlara bakmak için:

Get-Message -ResultSize Unlimited | Where-Object {$_.Status -eq "Retry"} | 
Select-Object Identity, FromAddress, Subject, Status, LastError | 
Format-List

Yaygın Sorun Senaryoları ve Çözümleri

Senaryo 1: Harici Mail Gönderilemiyor, İç Mail Çalışıyor

Bu en sık karşılaşılan durum. Kullanıcılar şirket içi mailleri alıp gönderebiliyor ama dışarıya hiçbir şey gitmiyor. Hemen Remote Delivery kuyruğuna bakıyorsunuz, yüzlerce mesaj “Retry” durumunda.

İlk kontrol noktası DNS:

# Exchange sunucusundan MX kaydı sorgulama
Resolve-DnsName -Name "hedefdomain.com" -Type MX -Server 8.8.8.8

# Smart host kullanıyorsanız smart host'a telnet testi
Test-NetConnection -ComputerName "smarthost.provider.com" -Port 25

Eğer DNS sorgusu başarısız oluyorsa veya Exchange sunucunuzun internet DNS’e erişimi yoksa, transport servisi harici MX kayıtlarını çözümleyemiyor demektir. Bunu kurumsal ortamlarda çok görüyorum, birisi firewall kuralı değiştirmiş ya da DNS server ayarları bozulmuş.

Send Connector üzerindeki DNS ayarlarını kontrol edin:

Get-SendConnector | Select-Object Name, DNSRoutingEnabled, SmartHosts, SourceTransportServers | Format-List

DNSRoutingEnabled false ise ve SmartHosts boşsa, problem bulundunuz demektir.

Senaryo 2: Kuyruk Şişiyor Ama Mesajlar Teslim Edilemiyor

Bazen mesajlar kuyruğa giriyor ama hiç çıkmıyor. Bu durumda transport servisinin durumunu kontrol edin:

# Transport servisi durumu
Get-Service MSExchangeTransport | Select-Object Status, StartType

# Hub Transport'u yeniden başlatmak (dikkatli kullanın!)
Restart-Service MSExchangeTransport -Force

Transport servisini yeniden başlatmadan önce mutlaka kuyruktaki mesaj sayısını ve kritikliğini değerlendirin. Servis yeniden başladığında kuyruklar temizlenmez, mesajlar korunur ama kısa süreli bir aksaklık yaşanır.

Senaryo 3: Poison Message Queue’da Mesaj Var

Poison queue’da mesaj görmek normalin dışında bir durumdur ve genellikle bozuk ya da işlenemeyen bir mesajın transport servisini çökertmeye başladığını gösterir.

# Poison queue'daki mesajları listele
Get-Message -Queue "SUNUCUADIPoison" | Format-List

# Mesajı resume etmek (dikkatli olun!)
Resume-Message -Identity "SUNUCUADIPoisonMessageID"

# Ya da direkt sil
Remove-Message -Identity "SUNUCUADIPoisonMessageID" -WithNDRNotification $false

Poison queue mesajlarını silmeden önce mesajın içeriğini ve kimden geldiğini mutlaka analiz edin. Bazen bu mesajlar güvenlik araştırması gerektiren şüpheli içerikler olabilir.

Kuyruk Yönetiminde Toplu İşlemler

Gerçek hayatta yüzlerce mesajı tek tek yönetmek imkansız. Toplu işlemler için filtreleme yeteneklerini kullanmak gerekir.

Belirli bir göndericiden gelen tüm mesajları askıya almak:

Get-Message -ResultSize Unlimited | 
Where-Object {$_.FromAddress -like "*[email protected]*"} | 
Suspend-Message

Belirli bir hedef domaindeki tüm mesajları silmek ve NDR göndermek:

Get-Message -ResultSize Unlimited | 
Where-Object {$_.Recipients -like "*@hedefdomain.com*"} | 
Remove-Message -WithNDRNotification $true

Retry durumundaki tüm mesajları zorla yeniden denemek:

Get-Queue | Where-Object {$_.Status -eq "Retry"} | Retry-Queue

Bu son komut özellikle geçici bir ağ sorunu çözüldükten sonra çok işe yarar. Exchange normalde yeniden denemeyi otomatik yapar ama siz bunu hızlandırmak istiyorsanız bu komutu kullanabilirsiniz.

Mail Flow Test ve Sorun Giderme Araçları

Test-Mailflow Komutu

Exchange’in kendi içinde mail akışını test eden bu araç çok değerli:

# Kendi kendine mail akış testi
Test-Mailflow -TargetMailboxServer SUNUCUADI

# Harici adrese test (dikkat: gerçek mail gönderir)
Test-Mailflow -TargetEmailAddress "[email protected]"

Çıktıdaki TestMailflowResult başarılı olmalı, MessageLatencyTime ise fikir verir. Bu değer normalde birkaç saniye olmalıdır, dakikalara ulaşıyorsa kuyruk gecikmesi var demektir.

SMTP Bağlantı Testi

Dışarıdan Exchange’e bağlantıyı test etmek için telnet kullanmak hala en güvenilir yöntem:

# PowerShell ile SMTP banner testi
$client = New-Object System.Net.Sockets.TcpClient
$client.Connect("exchange.sirket.com", 25)
$stream = $client.GetStream()
$reader = New-Object System.IO.StreamReader($stream)
$reader.ReadLine()

Ya da daha basit şekilde:

Test-NetConnection -ComputerName "exchange.sirket.com" -Port 25 -InformationLevel Detailed

Bu komutun çıktısında TcpTestSucceeded: True görüyorsanız portlar açık demektir. Eğer bağlantı başarısız oluyorsa firewall veya ağ katmanında sorun var.

Back Pressure Mekanizması ve Kaynak Yönetimi

Exchange’in pek bilinmeyen ama kritik özelliklerinden biri Back Pressure sistemidir. Exchange, sistem kaynaklarını (disk alanı, bellek, işlemci) sürekli izler ve kaynaklar kritik seviyeye yaklaştığında mail kabulünü yavaşlatır veya tamamen durdurur.

# Back pressure kayıtlarını görüntüle
Get-EventLog -LogName Application -Source "MSExchangeTransport" | 
Where-Object {$_.EventID -in @(15004, 15005, 15006, 15007)} | 
Select-Object TimeGenerated, EventID, Message | 
Format-List

Event ID’leri ve anlamları:

  • 15004: Kaynak baskısı başladı, yeni bağlantı kabulü azaltılıyor
  • 15005: Kaynak baskısı kritik, yeni mail kabulü durduruldu
  • 15006: Disk alanı kritik seviyede
  • 15007: Sistem belirli bir kaynak için Back Pressure’dan çıktı

Transport servisinin kaynak limitlerini görmek için:

# EdgeTransport.exe.config dosyasındaki Back Pressure ayarları
# Genellikle C:Program FilesMicrosoftExchange ServerV15Bin altında
Get-Content "C:Program FilesMicrosoftExchange ServerV15BinEdgeTransport.exe.config" | 
Select-String "resource|pressure" -CaseSensitive

Back Pressure’dan kaynaklanan sorunların çözümü genellikle basittir: disk temizleme, log dosyalarını arşivleme veya geçici dosyaları silme. Ama doğru teşhis yapmazsanız transport servisini kaç kere yeniden başlatırsanız başlatın sorunu çözemezsiniz.

Transport Log Analizi

Sorunları geriye dönük analiz etmek için transport logları altın değerindedir. Exchange, her SMTP konuşmasını detaylı loglar:

# Protocol loglarının yeri
Get-TransportService | Select-Object Name, ReceiveProtocolLogPath, SendProtocolLogPath

# Son bir saatteki log girişlerini analiz et
$logPath = "C:Program FilesMicrosoftExchange ServerV15TransportRolesLogsFrontEndProtocolLogSmtpReceive"
Get-ChildItem $logPath -Filter "*.log" | 
Where-Object {$_.LastWriteTime -gt (Get-Date).AddHours(-1)} | 
ForEach-Object { Get-Content $_.FullName } | 
Select-String "550|421|451" | 
Select-Object -Last 50

Burada aradığımız SMTP hata kodları:

  • 421: Servis geçici olarak kullanılamıyor (genellikle back pressure)
  • 451: İşlem hatası, geçici sorun
  • 550: Kalıcı teslim hatası, mesaj reddedildi

Bu logları analiz etmek başlangıçta zor gelebilir ama zamanla hangi hata kodunun ne anlama geldiğini içgüdüsel olarak tanımaya başlarsınız.

Gerçek Dünya: Toplu NDR Saldırısı Senaryosu

Özellikle anlamamış olunabilecek ama sysadminlerin korkulu rüyası olan bir durum: NDR saldırısı (backscatter). Spammerlar sahte gönderici adresi olarak sizin domaininizi kullanıyor, mesajlar teslim edilemiyor ve tüm NDR’lar sizin sunucunuza dönüyor.

Bu durumu tespit etmek için:

# Kuyruktaki NDR yüzdesi
$totalMessages = (Get-Message -ResultSize Unlimited).Count
$ndrMessages = (Get-Message -ResultSize Unlimited | Where-Object {$_.Subject -like "*Undeliverable*" -or $_.Subject -like "*Delivery Failed*"}).Count
Write-Host "Toplam: $totalMessages, NDR: $ndrMessages, Oran: $([math]::Round($ndrMessages/$totalMessages*100,2))%"

Eğer NDR oranı yüzde 30’un üzerindeyse muhtemelen backscatter yaşıyorsunuzdur.

Çözüm olarak önce NDR flood’u durdurmak gerekir:

# Belirli bir süre NDR gönderimini devre dışı bırak
Set-RemoteDomain Default -NDREnabled $false

# Ya da belirli IP'lerden gelen bağlantıları engelle
New-ReceiveConnector -Name "BlockedIPs" -Bindings "0.0.0.0:25" -RemoteIPRanges "Saldirgan_IP_Araligi"

Sonrasında SPF, DKIM ve DMARC kayıtlarınızı mutlaka gözden geçirin. Bu protokoller tam olarak bu tür saldırıları önlemek için var.

Kuyruk İzleme Otomasyonu

Manuel kontrol yapmak yerine proaktif izleme sistemi kurmak çok daha sağlıklı. Basit ama etkili bir izleme scripti:

# Kuyruk Alarm Scripti - Görev Zamanlayıcıya eklenebilir
$threshold = 100  # Bu sayının üzerinde mesaj varsa alarm
$smtpServer = "localhost"
$alertEmail = "[email protected]"

$problemQueues = Get-Queue | Where-Object {$_.MessageCount -gt $threshold -and $_.Status -ne "Suspended"}

if ($problemQueues) {
    $body = "Asagidaki kuyruklar esik degeri asiyor:`n`n"
    foreach ($queue in $problemQueues) {
        $body += "Kuyruk: $($queue.Identity)`n"
        $body += "Mesaj Sayisi: $($queue.MessageCount)`n"
        $body += "Durum: $($queue.Status)`n"
        $body += "Son Hata: $($queue.LastError)`n`n"
    }
    
    Send-MailMessage -From "[email protected]" `
                     -To $alertEmail `
                     -Subject "Exchange Kuyruk Alarmi - $([datetime]::Now)" `
                     -Body $body `
                     -SmtpServer $smtpServer
}

Bu scripti Windows Görev Zamanlayıcı’ya her 15 dakikada bir çalışacak şekilde ekleyin. Sabah ofise geldiğinizde sorun yoksa mailbox’ınız boş olacak, sorun varsa alarm gelmiş olacak.

Mesaj İzleme ile Kaybolmuş Mailleri Bulma

Kullanıcılar “mail gitmiyor” dediğinde ilk başvuracağınız araç Message Tracking:

# Belirli bir kullanıcının son 24 saatteki mail geçmişi
Get-MessageTrackingLog -Sender "[email protected]" `
                       -Start (Get-Date).AddDays(-1) `
                       -ResultSize Unlimited | 
Select-Object Timestamp, EventId, Source, Recipients, MessageSubject | 
Format-Table -AutoSize

# Belirli bir alıcıya gelen mailleri izle
Get-MessageTrackingLog -Recipients "[email protected]" `
                       -Start (Get-Date).AddHours(-4) `
                       -EventId DELIVER | 
Select-Object Timestamp, Sender, MessageSubject

EventId değerleri:

  • RECEIVE: Mesaj alındı
  • DELIVER: Mailbox’a teslim edildi
  • SEND: Dışarıya gönderildi
  • FAIL: Teslim başarısız
  • REDIRECT: Mesaj yönlendirildi
  • RESOLVE: Alıcı adresi çözümlendi

Bu loglar 30 gün tutulur ve bir kullanıcının “mailim kayboldu” şikayetinde neler olduğunu dakika dakika takip etmenizi sağlar.

Receive Connector Sorunları

Bazen sorun gönderimde değil, mail kabulünde olur. Özellikle üçüncü parti uygulamalar (ERP sistemleri, yazıcılar, monitoring araçları) Exchange üzerinden mail gönderirken sorun yaşayabilir.

# Mevcut Receive Connector'ları listele
Get-ReceiveConnector | Select-Object Name, Bindings, RemoteIPRanges, AuthMechanism, PermissionGroups | Format-List

# Belirli bir IP'nin hangi connector'ı kullandığını test et
# Exchange Management Shell'de
Get-ReceiveConnector | Where-Object {$_.RemoteIPRanges -match "192.168.1.100"}

Uygulama sunucuları için en sık yapılan hata, Receive Connector’a yanlış IP aralığı tanımlamak ya da AnonymousUsers iznini vermemek. Relay izni vermeden uygulama sunucusu mail gönderemez.

# Relay yetkisi olan connector oluşturma
New-ReceiveConnector -Name "Uygulama Relay" `
                     -TransportRole FrontendTransport `
                     -Custom `
                     -Bindings "0.0.0.0:25" `
                     -RemoteIPRanges "192.168.1.100/32","192.168.1.101/32"

# Anonim relay iznini ver
Set-ReceiveConnector "Uygulama Relay" -PermissionGroups AnonymousUsers
Get-ReceiveConnector "Uygulama Relay" | Add-ADPermission -User "NT AUTHORITYANONYMOUS LOGON" -ExtendedRights "Ms-Exch-SMTP-Accept-Any-Recipient"

Dikkat: Bu yapılandırmayı sadece güvendiğiniz iç IP adresleri için yapın. RemoteIPRanges’ı herkese açık bırakmak açık relay oluşturur ve sunucunuzu spam cenneti haline getirir.

Sonuç

Exchange kuyruk yönetimi, mail altyapısının sağlıklı çalışmasının temel taşlarından biri. Sorunlar genellikle üç ana kategoride toplanır: ağ ve DNS sorunları, kaynak yetersizliği (disk, bellek) ve yanlış yapılandırma. Bu üç kategoriyi sistematik şekilde kontrol edebildiğinizde, büyük çoğunluğu çözebilirsiniz.

Benim önerim: Bu yazıdaki komutları bir “runbook” haline getirin. Sorun yaşandığında paniklemeden adım adım takip edeceğiniz bir kontrol listesi oluşturun. Get-Queue, Get-MessageTrackingLog ve transport event logları üçlüsü, yaşayacağınız sorunların yüzde doksanında size yol gösterecek.

Son olarak şunu söylemek isterim: Exchange’i iyi tanımak için mutlaka sorunlarla karşılaşmak gerekmiyor. Test ortamı kurarak farklı hata senaryolarını simüle edebilir, komutları rahatça deneyebilirsiniz. Gerçek üretim ortamında ilk kez bir komutu çalıştırmak hiç de iyi bir his değil, bunu deneyimleyerek öğrendim.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir