Mail sunucusu yönetiminin en karmaşık parçalarından biri, gelen ve giden postaların doğru şekilde yönlendirilmesi ve teslim edilmesidir. Exim’in routing ve transport mimarisi, bu işlemleri son derece esnek bir şekilde yapılandırmanıza olanak tanır. Ancak bu esneklik beraberinde öğrenme eğrisi de getiriyor. Bu yazıda Exim’in routing ve transport yapısını gerçek dünya senaryolarıyla birlikte ele alacağız.
Exim’in Routing ve Transport Mantığı
Exim, bir e-posta aldığında onu işlemek için belirli bir pipeline izler. Önce ACL (Access Control List) kuralları çalışır, ardından mesaj kuyruğa alınır ve router’lar devreye girer. Router’lar mesajın nereye gideceğini belirler. Transport ise mesajın oraya nasıl iletileceğini tanımlar.
Temel akış şu şekildedir:
- Routers: Alıcı adresini analiz eder ve mesajın teslim yöntemini seçer
- Transports: Seçilen yöntemle mesajı fiziksel olarak teslim eder
- Retry rules: Teslim başarısız olursa ne zaman tekrar deneneceğini belirler
- Rewrite rules: Adres dönüşüm kurallarını uygular
Exim konfigürasyon dosyası genellikle /etc/exim4/exim4.conf veya /etc/exim/exim.conf yolunda bulunur. cPanel/WHM ortamlarında ise /etc/exim.conf kullanılır.
Router Yapılandırması
Router’lar sırayla işlenir ve her router belirli koşullar altında devreye girer. Bir router eşleşme sağladığında ve başarıyla tamamlandığında, sonraki router’lara geçilmez (aksi açıkça belirtilmediği sürece).
Temel Router Yapısı
# /etc/exim4/exim4.conf içindeki örnek router tanımı
begin routers
localuser:
driver = accept
check_local_user
transport = local_delivery
cannot_route_message = Kullanici bulunamadi
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
Bu yapıda iki temel router görüyoruz. localuser router’ı yerel sistem kullanıcılarına posta teslim eder. dnslookup ise harici domainler için DNS MX kaydı sorgulaması yapar.
Smarthost Router Yapılandırması
Kurumsal ortamlarda çok sık karşılaştığım senaryo şu: Tüm giden postaları bir relay sunucusundan göndermek istiyorsunuz. Bunu smarthost router ile yapabilirsiniz.
# Smarthost üzerinden yönlendirme
smarthost:
driver = manualroute
domains = ! +local_domains
transport = remote_smtp_smarthost
route_list = * mail.relay.example.com byname
host_find_failed = defer
same_domain_copy_routing = yes
no_more
driver = manualroute: DNS sorgusu yapmadan belirtilen sunucuya yönlendir demektir. route_list: Hangi domain için hangi host kullanılacağını belirtir. * tüm domainler anlamına gelir.
Domain Bazlı Yönlendirme
Farklı domainleri farklı mail sunucularına yönlendirmek gerektiğinde bunu route_list içinde tanımlayabilirsiniz:
# Belirli domainleri özel sunuculara yönlendir
domain_specific_route:
driver = manualroute
domains = partner1.com : partner2.org : subsidiary.net
transport = remote_smtp
route_list = partner1.com mail.partner1.com ;
partner2.org smtp.partner2.org ;
subsidiary.net 192.168.10.5
no_more
Burada noktalı virgül ayracı her domain-host çiftini birbirinden ayırır. Bu yapıyı özellikle hybrid cloud ortamlarında, bazı domainler şirket içi bazıları bulutta barındırıldığında kullanıyorum.
Koşullu Routing: Condition Direktifi
Router’lara koşul eklemek oldukça güçlü senaryolar oluşturmanızı sağlar:
# Sadece belirli saatlerde veya koşullarda çalışan router
business_hours_route:
driver = dnslookup
domains = ! +local_domains
condition = ${if and{
{>{$tod_hours}{8}}
{<{$tod_hours}{18}}
}{yes}{no}}
transport = remote_smtp
no_more
# VIP kullanıcılar için öncelikli router
vip_sender_route:
driver = dnslookup
domains = ! +local_domains
senders = [email protected] : [email protected] : [email protected]
transport = remote_smtp_priority
no_more
Transport Yapılandırması
Transport, mesajın gerçekten nasıl teslim edileceğini tanımlar. En yaygın kullandığım transport türleri şunlardır:
- smtp: Uzak sunucuya SMTP ile teslim
- local_delivery: Lokal dosya sistemine teslim (mailbox)
- pipe: Bir programa pipe ederek teslim
- appendfile: Dosyaya ekleme
SMTP Transport Yapılandırması
begin transports
remote_smtp:
driver = smtp
message_size_limit = ${if > {$max_received_linelength}{998}{1}{0}}
hosts_avoid_tls = <; 0.0.0.0/0
remote_smtp_smarthost:
driver = smtp
hosts = mail.relay.example.com
port = 587
hosts_require_auth = mail.relay.example.com
hosts_require_tls = mail.relay.example.com
tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt
hosts_require_auth: Belirtilen host’a bağlanırken kimlik doğrulama zorunlu. hosts_require_tls: TLS şifreleme zorunlu. Bu iki direktifi production ortamlarda mutlaka kullanın.
TLS ile Güvenli SMTP Transport
# TLS zorunlu, modern cipher suite'lerle güvenli transport
remote_smtp_tls:
driver = smtp
port = 465
hosts_require_tls = *
tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt
tls_require_ciphers = ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
ECDH+AES128:DH+AES:!aNULL:!MD5:!DSS
tls_try_verify_hosts = *
dnssec_request_domains = *
Özellikle finans sektörü müşterilerinde bu konfigürasyonu kullanıyorum. DNSSEC ve zorunlu TLS ile man-in-the-middle saldırılarına karşı ciddi bir koruma sağlanmış oluyor.
Local Delivery Transport
# Yerel kullanıcıya Maildir formatında teslim
local_delivery:
driver = appendfile
directory = $home/Maildir
maildir_format = true
delivery_date_add
envelope_to_add
return_path_add
group = mail
mode = 0660
mode_fail_narrower = false
# Mbox formatında teslim (eski sistemler için)
local_mbox:
driver = appendfile
file = /var/mail/$local_part
delivery_date_add
envelope_to_add
return_path_add
group = mail
mode = 0660
Maildir formatı dosya kilitleme sorunları yaşamadığı için modern sistemlerde kesinlikle tercih edilmeli. Özellikle yüksek trafikli sunucularda mbox’ın kilitleme sorunları can sıkıcı olabiliyor.
Pipe Transport: Filtreleme ve İşleme
Postaları işlemek için bir programa yönlendirmeniz gerektiğinde pipe transport kullanırsınız. SpamAssassin veya özel işleme scriptleri için idealdir:
# SpamAssassin ile spam kontrolü için pipe transport
spamcheck_transport:
driver = pipe
command = /usr/bin/spamc -u $local_part
use_bsmtp = true
transport_filter = /usr/sbin/exim4 -oMr spam-scanned -bS
home_directory = /tmp
current_directory = /tmp
user = mail
group = mail
log_output = true
return_fail_output = true
message_prefix =
message_suffix =
Gerçek Dünya Senaryoları
Senaryo 1: Çoklu Domain, Çoklu Backend
Bir hosting ortamında yüz farklı domainle çalışıyorsunuz. Bazı domainler kendi mail sunucularına sahip, bazıları sizin sunucunuzda barındırılıyor.
# Harici domain listesi için dosya bazlı router
external_domains_router:
driver = manualroute
domains = lsearch;/etc/exim4/external_domains.list
transport = remote_smtp
route_list = lsearch;/etc/exim4/domain_routes.list
no_more
local_domains_router:
driver = accept
domains = lsearch;/etc/exim4/local_domains.list
local_parts = lsearch;/etc/exim4/local_addresses.list
transport = local_delivery
/etc/exim4/domain_routes.list dosyası şu şekilde görünür:
# domain_routes.list
domain1.com mail.domain1.com
domain2.org 10.0.1.50
domain3.net mx.provider.com byname
Bu yapıyı birden fazla ISP için mail yönetimi yapan bir ortamda kullandım. Yüzlerce domain’in routing’ini tek bir dosya üzerinden yönetmek büyük kolaylık sağlıyor.
Senaryo 2: Bounce Yönetimi ve DSN Konfigürasyonu
Delivery Status Notification’ları düzgün yönetmek, özellikle bulk mail gönderen ortamlarda kritiktir:
# Bounce mesajlarını özel adrese yönlendir
begin routers
bounce_handler:
driver = accept
senders = :
local_parts = bounce-handler
domains = +local_domains
transport = bounce_processing_pipe
begin transports
bounce_processing_pipe:
driver = pipe
command = /usr/local/bin/process_bounce.py
user = mailhandler
group = mail
log_output = true
Bu router, envelope from adresi boş olan (bounce mesajları) ve [email protected] adresine gelen mesajları yakalar ve işleme scriptine yönlendirir. E-posta pazarlama platformlarında suppression list yönetimi için hayat kurtarıcı bir yapı.
Senaryo 3: Rate Limiting ile Spam Kontrolü
Giden spam’i engellemek için router seviyesinde kontrol ekleyebilirsiniz:
# Kullanıcı bazlı rate limiting router
rate_limited_smtp:
driver = dnslookup
domains = ! +local_domains
ratelimit = 100 / 1h / strict / $sender_address
transport = remote_smtp
no_more
# exim4.conf içinde global rate limit ayarı
RATELIMIT_PER_USER = 100
RATELIMIT_WINDOW = 1h
begin routers
outgoing_ratelimit:
driver = dnslookup
domains = ! +local_domains
condition = ${if ratelimit{$sender_address}{RATELIMIT_PER_USER/RATELIMIT_WINDOW/strict/per_addr}{no}{yes}}
transport = remote_smtp
no_more
Retry Kuralları
Router ve transport yapısını tamamlamak için retry kurallarını da anlamak gerekiyor. Teslim başarısız olduğunda Exim ne yapacak?
begin retry
# Genel retry kuralı
# Format: address error retries
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
# Belirli bir domain için özel retry
gmail.com * F,1h,10m; F,8h,2h
# 4xx geçici hatalar için agresif retry
* 4?? F,30m,5m; F,4h,30m; F,24h,2h
# Bağlantı reddinde daha uzun bekle
* connection_refused F,30m,10m; F,4h,1h; F,5d,4h
Retry kurallarının formatını açıklayalım:
- F,2h,15m: 2 saat boyunca 15 dakikada bir dene (Fixed interval)
- G,16h,1h,1.5: 16 saat boyunca, 1 saatten başlayıp 1.5 çarpanıyla artan aralıklarla dene (Geometric)
Logging ve Debugging
Konfigürasyonunuzu test ederken ve sorun giderirken şu komutları sık kullanıyorum:
# Routing testini simüle et (mesaj göndermeden)
exim -bt [email protected]
# Detaylı routing debug çıktısı
exim -d+routing -bt [email protected]
# Belirli bir mesajın routing'ini test et
exim -d -bh 192.168.1.100
# Konfigürasyon dosyasını kontrol et
exim -bV
# Mail kuyruğunu görüntüle
exim -bp
# Belirli bir mesajı yeniden dene
exim -M message-id
# Transport log'larını canlı izle
tail -f /var/log/exim4/mainlog | grep -E "router|transport"
# Exim konfigürasyonunu syntax kontrolü ile test et
exim -C /etc/exim4/exim4.conf -bV
# Routing kararlarını detaylı gör
exim -d+all -bt [email protected] 2>&1 | grep -E "router|transport|deliver"
Adres Rewrite Kuralları
Transport öncesinde adresleri dönüştürmeniz gerekebilir. Örneğin, eski domain adından yeni domain adına geçiş yapıyorsunuz:
begin rewrite
# Eski domain'den yeni domain'e rewrite
*@eski-domain.com ${local_part}@yeni-domain.com FfrsTt
# Harici görünüm için rewrite (gönderen adresi düzeltme)
*@internal.company.com ${local_part}@company.com FfrsTt
# Postmaster adresini yönetici'ye yönlendir
postmaster@* [email protected] FfrsTt
Rewrite flag’lerinin anlamları:
- F: From header’ını rewrite et
- f: Envelope from’u rewrite et
- T: To header’ını rewrite et
- t: Envelope to’yu rewrite et
- r: Reply-To header’ını rewrite et
- s: Sender header’ını rewrite et
Performans Optimizasyonu
Yüksek trafikli ortamlarda transport konfigürasyonunda dikkat etmeniz gereken bazı parametreler var:
# Paralel bağlantı sayısını optimize et
remote_smtp:
driver = smtp
hosts_try_fastopen = *
connection_max_messages = 500
helo_name = mail.sirketiniz.com
# Bağlantı başına maksimum mesaj sayısı
smtp_accept_max = 150
smtp_accept_max_per_host = 10
smtp_accept_queue_per_connection = 10
# Queue runner ayarları
queue_run_max = 5
remote_max_parallel = 10
# Büyük sunucular için gelişmiş ayarlar
# /etc/exim4/exim4.conf içine ekleyin
# SMTP bağlantı zaman aşımı
smtp_connect_timeout = 30s
smtp_write_timeout = 5m
# Paralel delivery worker sayısı
deliver_queue_load_max = 10
queue_smtp_domains = *
# DNS cache optimizasyonu
dns_again_means_nonexist = ! .
dns_check_names_pattern = ^(([-a-z0-9]+.)+[a-z]{2,}.?)$
Yaygın Sorunlar ve Çözümleri
Freeze olan mesajlar: Exim bazen mesajları freeze eder. Toplu unfreeze için:
# Tüm frozen mesajları unfreeze et
exiqgrep -z -i | xargs exim -Mt
# Freeze olan ve bounce olan mesajları sil
exiqgrep -z -i | xargs exim -Mrm
Relay denied hatası: Router’larınızda domain listesi yanlış yapılandırılmış olabilir. exim -bt komutuyla routing kararını test edin.
TLS handshake hataları: hosts_avoid_tls veya hosts_require_tls direktiflerini kontrol edin. Modern Exim versiyonlarında TLS 1.0/1.1 varsayılan olarak devre dışı bırakılmıştır.
Yüksek kuyruk derinliği: exim -bp | exiqsumm komutuyla kuyruk özetini görüntüleyin. Sorunlu domain’leri tespit edip geçici olarak transport_home_directory ve connection_max_messages değerlerini ayarlayın.
Sonuç
Exim’in routing ve transport mimarisi, ilk bakışta karmaşık görünse de mantığını kavradıktan sonra son derece güçlü ve esnek bir yapı sunuyor. Önemli noktalara bakacak olursak:
- Router’lar sırayla işlenir, ilk eşleşen router kazanır. Router sıralamanıza dikkat edin
- Transport konfigürasyonunda TLS ve kimlik doğrulamayı ihmal etmeyin
- Retry kurallarını domain’in özelliğine göre özelleştirin
- Logging ve
exim -btkomutu sorun gidermede en değerli araçlarınız - Yüksek trafikli ortamlarda paralel bağlantı ve kuyruk ayarlarını mutlaka optimize edin
Production’da değişiklik yapmadan önce her zaman exim -C yeni_conf.conf -bV ile syntax kontrolü yapın ve exim -d+routing -bt [email protected] ile routing kararlarını simüle edin. Mail sunucusu yanlış yapılandırması hem iş sürekliliğini hem de domain reputation’ı doğrudan etkileyen bir konudur.